0

我有一个使用 PostgreSQL generate_series 函数的查询,但是当涉及到大量数据时,查询可能会很慢。生成查询的代码示例如下:

$yesterday = date('Y-m-d',(strtotime ( '-1 day' ) ));


            $query = "
            WITH interval_step AS (
            SELECT gs::date AS interval_dt, random() AS r 
            FROM generate_series('$yesterday'::timestamp, '2015-01-01', '1 day') AS gs)
            SELECT articles.article_id, article_title, article_excerpt, article_author, article_link, article_default_image, article_date_published, article_bias_avg, article_rating_avg
            FROM development.articles JOIN interval_step ON articles.article_date_added::date=interval_step.interval_dt ";

            if (isset($this -> registry -> get['category'])) {
                $query .= "
                JOIN development.feed_articles ON articles.article_id = feed_articles.article_id
                JOIN development.rss_feeds ON feed_articles.rss_feed_id = rss_feeds.rss_feed_id
                JOIN development.news_categories ON rss_feeds.news_category_id = news_categories.news_category_id
                WHERE news_category_name = $1";

                $params = array($category_name);
                $query_name = 'browse_category';
            }

            $query .= " ORDER BY interval_step.interval_dt DESC, RANDOM() LIMIT 20;";

本系列仅查找前一天的内容,并按随机顺序对结果进行排序。我的问题是什么是 generate_series 可以优化以提高性能?

4

2 回答 2

1

random()恕我直言,请尝试在您的order by声明中删除它。它的性能影响可能比您想象的要大得多。事实上,它可能是按 订购整套产品interval_dt desc, random(),然后选择前 20 名。不建议...

尝试获取例如 100 行 order by interval_dt desc,然后按照相同的逻辑对它们进行洗牌,并在您的应用程序中选择 20 行。或者将整个事情包装在一个子查询limit 100中,并按照相同的行相应地重新排序。

于 2013-07-02T18:53:13.073 回答
1

你根本不需要那个generate_series。并且不要连接查询字符串。如果未设置,则通过将参数设为空字符串(或 null)来避免它:

if (!isset($this -> registry -> get['category']))
    $category_name = '';

$query = "
    select articles.article_id, article_title, article_excerpt, article_author, article_link, article_default_image, article_date_published, article_bias_avg, article_rating_avg
    from
        development.articles
        inner join
        development.feed_articles using (article_id)
        inner join
        development.rss_feeds using (rss_feed_id)
        inner join
        development.news_categories using (news_category_id)
    where
        (news_category_name = $1 or $1 = '')
        and articles.article_date_added >= current_date - 1
    order by
        date_trunc('day', articles.article_date_added) desc,
        random()
    limit 20;
";

$params = array($category_name);

$yesterday也不需要传递给查询,因为它可以完全在 SQL 中完成。

如果$category_name为空,它将返回所有类别:

(news_category_name = $1 or $1 = '')
于 2013-07-03T07:54:20.003 回答