当我在桌面上执行第一个查询时,我遇到了麻烦。即使我更改要查找的范围日期,后续查询也会快得多。我假设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
提前致谢
答案 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_mem
,maintenance_work_mem
)以了解可能会消耗多少RAM,因此我的effective_cache_size
估算值是正确的大多数时候。
但是如果你刚开启你的Postgres,第一次查询很可能会很长,因为OS文件缓存和共享缓冲区中没有数据。您可以使用高级EXPLAIN
选项进行检查:
EXPLAIN (ANALYZE, BUFFERS) SELECT ...
- 您将看到从磁盘(&#34;读取&#34;)或缓存中获取了多少缓冲区(&#34;点击&#34;)
在这里,您可以找到有关使用EXPLAIN
:http://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
在所有数据库或涉及的表中。尝试在数据库级别执行它。