第一次查询时速度慢

时间:2017-06-28 17:23:29

标签: postgresql

当我在桌面上执行第一个查询时,我遇到了麻烦。即使我更改要查找的范围日期,后续查询也会快得多。我假设PostgreSQL实现了一种缓存机制,允许后续查询更快。我可以尝试预热缓存,以便第一个用户请求可以访问缓存。但是,我想我可以以某种方式改进以下查询:

SELECT
    y.id, y.title, x.visits, x.score
FROM (
    SELECT
        article_id, visits,
        COALESCE(ROUND((visits / NULLIF(hits ,0)::float)::numeric, 4), 0) score
    FROM (
        SELECT
            article_id, SUM(visits) visits, SUM(hits) hits
        FROM
            article_reports
        WHERE
            a.site_id = 'XYZ' AND a.date >= '2017-04-13'  AND a.date <= '2017-06-28'
        GROUP BY
            article_id
    ) q ORDER BY score DESC, visits DESC LIMIT(20)
) x 
INNER JOIN 
    articles y ON x.article_id = y.id

关于如何改进这一点的任何想法。以下是EXPLAIN的结果:

   Nested Loop  (cost=84859.76..85028.54 rows=20 width=272) (actual time=12612.596..12612.836 rows=20 loops=1)
  ->  Limit  (cost=84859.34..84859.39 rows=20 width=52) (actual time=12612.502..12612.517 rows=20 loops=1)
    ->  Sort  (cost=84859.34..84880.26 rows=8371 width=52) (actual time=12612.499..12612.503 rows=20 loops=1)
          Sort Key: q.score DESC, q.visits DESC
          Sort Method: top-N heapsort  Memory: 27kB
          ->  Subquery Scan on q  (cost=84218.04..84636.59 rows=8371 width=52) (actual time=12513.168..12602.649 rows=28965 loops=1)
                ->  HashAggregate  (cost=84218.04..84301.75 rows=8371 width=36) (actual time=12513.093..12536.823 rows=28965 loops=1)
                      Group Key: a.article_id
                      ->  Bitmap Heap Scan on article_reports a  (cost=20122.78..77122.91 rows=405436 width=36) (actual time=135.588..11974.774 rows=398242 loops=1)
                            Recheck Cond: (((site_id)::text = 'XYZ'::text) AND (date >= '2017-04-13'::date) AND (date <= '2017-06-28'::date))
                            Heap Blocks: exact=36911
                            ->  Bitmap Index Scan on index_article_reports_on_site_id_and_article_id_and_date  (cost=0.00..20021.42 rows=405436 width=0) (actual time=125.846..125.846 rows=398479 loops=1)"
                                  Index Cond: (((site_id)::text = 'XYZ'::text) AND (date >= '2017-04-13'::date) AND (date <= '2017-06-28'::date))
  ->  Index Scan using articles_pkey on articles y  (cost=0.42..8.44 rows=1 width=128) (actual time=0.014..0.014 rows=1 loops=20)
       Index Cond: (id = q.article_id)
 Planning time: 1.443 ms
 Execution time: 12613.689 ms

提前致谢

2 个答案:

答案 0 :(得分:2)

有两个级别的&#34;缓存&#34; Postgres使用:

  • 操作系统文件缓存
  • 共享缓冲区。

重要说明:Postgres只能直接控制第二个,并且依赖于第一个,这是在OS&#39;控制。

我要检查的第一件事是postgresql.conf中的这两个设置:

  • effective_cache_size - 通常我将其设置为所有可用RAM的~3 / 4。请注意,它不是一个告诉Postgres如何分配内存的设置,它只是一个建议&#34;到Postgres计划员告诉一些OS文件缓存大小的估计
  • shared_buffers - 通常我将其设置为RAM大小的1/4。这是分配设置。

此外,我还要检查其他与内存相关的设置(work_memmaintenance_work_mem)以了解可能会消耗多少RAM,因此我的effective_cache_size估算值是正确的大多数时候。

但是如果你刚开启你的Postgres,第一次查询很可能会很长,因为OS文件缓存和共享缓冲区中没有数据。您可以使用高级EXPLAIN选项进行检查:

EXPLAIN (ANALYZE, BUFFERS) SELECT ...

- 您将看到从磁盘(&#34;读取&#34;)或缓存中获取了多少缓冲区(&#34;点击&#34;)

在这里,您可以找到有关使用EXPLAINhttp://www.dalibo.org/_media/understanding_explain.pdf

的优质资料

此外,有一个扩展旨在解决&#34;冷缓存&#34;问题:pg_prewarm https://www.postgresql.org/docs/current/static/pgprewarm.html

此外,使用SSD磁盘而不是磁盘也意味着磁盘读取速度会快得多。

玩得开心,工作得很好Postgres: - )

答案 1 :(得分:0)

如果是插入多行后的第一个查询,则必须运行

ANALYZE

在所有数据库或涉及的表中。尝试在数据库级别执行它。