我在表上执行第一个查询时遇到了麻烦。后续查询要快得多,即使我更改了要查找的范围日期。我假设 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
Run Code Online (Sandbox Code Playgroud)
关于如何改进这一点的任何想法。以下是 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
Run Code Online (Sandbox Code Playgroud)
提前致谢
Nic*_*ick 10
Postgres 使用两个级别的“缓存”:
重要提示:Postgres 只直接控制第二个,并依赖于第一个,这是在操作系统的控制之下。
我要检查的第一件事是 postgresql.conf 中的这两个设置:
effective_cache_size– 通常我将其设置为所有可用 RAM 的 3/4。请注意,它不是告诉 Postgres 如何分配内存的设置,它只是给 Postgres 规划器的“建议”,告诉一些操作系统文件缓存大小的估计shared_buffers– 通常我将其设置为 RAM 大小的 1/4。这是分配设置。此外,我会检查其他与内存相关的设置 ( work_mem, maintenance_work_mem) 以了解可能消耗多少 RAM,因此我的effective_cache_size估计在大多数情况下是否正确。
但是如果你刚刚打开你的 Postgres,第一个查询很可能会很长,因为操作系统文件缓存和共享缓冲区中没有数据。您可以使用高级EXPLAIN选项进行检查:
EXPLAIN (ANALYZE, BUFFERS) SELECT ...
Run Code Online (Sandbox Code Playgroud)
-- 您将看到从磁盘(“读取”)或缓存(“命中”)获取了多少缓冲区
在这里你可以找到关于使用的好材料EXPLAIN:http : //www.dalibo.org/_media/understanding_explain.pdf
此外,还有一个旨在解决“冷缓存”问题的扩展:pg_prewarm https://www.postgresql.org/docs/current/static/pgprewarm.html
此外,使用 SSD 磁盘而不是磁性磁盘意味着磁盘读取速度会快得多。
玩得开心,Postgres 运行良好:-)
| 归档时间: |
|
| 查看次数: |
4317 次 |
| 最近记录: |