Postgresql
具有 35m 行慢查詢的 Postgres 表。我怎樣才能提高性能?
SELECT count(c.id) as clickCount FROM clicks c LEFT JOIN links l on c.link_id = l.id LEFT JOIN user_agents ua on c.user_agent_id = ua.id AND ua.robot IS NULL WHERE l.user_id = ? QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate (cost=337670.79..337670.80 rows=1 width=8) (actual time=3508.630..3508.630 rows=1 loops=1) Buffers: shared hit=448334 -> Nested Loop (cost=0.84..334057.39 rows=1445360 width=4) (actual time=0.041..3040.606 rows=6110334 loops=1) Buffers: shared hit=448334 -> Index Scan using link_user_idx on links l (cost=0.28..73.63 rows=136 width=4) (actual time=0.017..0.093 rows=136 loops=1) Index Cond: (user_id = 1125) Buffers: shared hit=24 -> Index Scan using click_link_idx on clicks c (cost=0.56..2208.66 rows=24710 width=12) (actual time=0.003..16.136 rows=44929 loops=136) Index Cond: (link_id = l.id) Buffers: shared hit=448310 Planning Time: 0.512 ms Execution Time: 3508.683 ms
3.5 秒
SELECT count(c.id) as clickCount, l.location FROM clicks c LEFT JOIN links l on c.link_id = l.id LEFT JOIN user_agents ua on c.user_agent_id = ua.id AND ua.robot IS NULL WHERE l.user_id = 1125 GROUP BY l.location ORDER BY clickCount, location DESC QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sort (cost=495348.44..495348.49 rows=18 width=524) (actual time=1978.261..1978.261 rows=1 loops=1) Sort Key: (count(c.id)), l.location DESC Sort Method: quicksort Memory: 25kB Buffers: shared hit=23740 read=38820 -> Finalize GroupAggregate (cost=495334.17..495348.07 rows=18 width=524) (actual time=1978.251..1978.251 rows=1 loops=1) Group Key: l.location Buffers: shared hit=23740 read=38820 -> Gather Merge (cost=495334.17..495347.35 rows=108 width=524) (actual time=1978.231..1997.869 rows=7 loops=1) Workers Planned: 6 Workers Launched: 6 Buffers: shared hit=153563 read=257052 -> Sort (cost=494334.08..494334.12 rows=18 width=524) (actual time=1956.989..1956.990 rows=1 loops=7) Sort Key: l.location DESC Sort Method: quicksort Memory: 25kB Worker 0: Sort Method: quicksort Memory: 25kB Worker 1: Sort Method: quicksort Memory: 25kB Worker 2: Sort Method: quicksort Memory: 25kB Worker 3: Sort Method: quicksort Memory: 25kB Worker 4: Sort Method: quicksort Memory: 25kB Worker 5: Sort Method: quicksort Memory: 25kB Buffers: shared hit=153563 read=257052 -> Partial HashAggregate (cost=494333.52..494333.70 rows=18 width=524) (actual time=1956.955..1956.956 rows=1 loops=7) Group Key: l.location Buffers: shared hit=153515 read=257052 -> Hash Join (cost=22.52..494165.25 rows=33654 width=520) (actual time=42.709..1738.826 rows=872905 loops=7) Hash Cond: (c.link_id = l.id) Buffers: shared hit=153515 read=257052 -> Parallel Seq Scan on clicks c (cost=0.00..476696.35 rows=6638735 width=12) (actual time=0.045..884.436 rows=5690344 loops=7) Buffers: shared hit=153257 read=257052 -> Hash (cost=22.29..22.29 rows=19 width=520) (actual time=0.219..0.219 rows=136 loops=7) Buckets: 1024 Batches: 1 Memory Usage: 15kB Buffers: shared hit=174 -> Bitmap Heap Scan on links l (cost=1.53..22.29 rows=19 width=520) (actual time=0.050..0.186 rows=136 loops=7) Recheck Cond: (user_id = 1125) Heap Blocks: exact=22 Buffers: shared hit=174 -> Bitmap Index Scan on link_user_idx (cost=0.00..1.52 rows=19 width=0) (actual time=0.036..0.036 rows=136 loops=7) Index Cond: (user_id = 1125) Buffers: shared hit=20 Planning Time: 0.334 ms Execution Time: 1998.071 ms
1.9 秒
SELECT sum(r.amount * c.revshare_influencer) as amount, r.month as month, r.year as year FROM revenue r JOIN clicks c on c.id = r.click_id WHERE r.user_id = 1125 GROUP BY r.year, r.month ORDER BY r.year desc, r.month desc QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize GroupAggregate (cost=57546.34..62229.59 rows=22711 width=40) (actual time=2765.425..2914.399 rows=13 loops=1) Group Key: r.year, r.month Buffers: shared hit=1755012 read=8976, temp read=1198 written=1204 -> Gather Merge (cost=57546.34..61621.83 rows=32388 width=40) (actual time=2762.219..2936.577 rows=52 loops=1) Workers Planned: 3 Workers Launched: 3 Buffers: shared hit=6407432 read=20902, temp read=4374 written=4398 -> Partial GroupAggregate (cost=56546.30..56816.20 rows=10796 width=40) (actual time=2749.492..2865.023 rows=13 loops=4) Group Key: r.year, r.month Buffers: shared hit=6407432 read=20902, temp read=4374 written=4398 -> Sort (cost=56546.30..56573.29 rows=10796 width=52) (actual time=2681.282..2736.792 rows=318604 loops=4) Sort Key: r.year DESC, r.month DESC Sort Method: external merge Disk: 9584kB Worker 0: Sort Method: external merge Disk: 8480kB Worker 1: Sort Method: external merge Disk: 8608kB Worker 2: Sort Method: external merge Disk: 8320kB Buffers: shared hit=6407432 read=20902, temp read=4374 written=4398 -> Nested Loop (cost=361.57..55823.06 rows=10796 width=52) (actual time=113.962..2503.475 rows=318604 loops=4) Buffers: shared hit=6407411 read=20902 -> Parallel Bitmap Heap Scan on revenue r (cost=361.01..27825.97 rows=10796 width=40) (actual time=113.683..358.398 rows=318604 loops=4) Recheck Cond: (user_id = 1125) Heap Blocks: exact=14271 Buffers: shared hit=37228 read=15519 -> Bitmap Index Scan on revenue_user_idx (cost=0.00..352.64 rows=33468 width=0) (actual time=104.289..104.289 rows=1274414 loops=1) Index Cond: (user_id = 1125) Buffers: shared read=3485 -> Index Scan using clicks_idx_id on clicks c (cost=0.56..2.59 rows=1 width=20) (actual time=0.006..0.006 rows=1 loops=1274414) Index Cond: (id = r.click_id) Buffers: shared hit=6370183 read=5383 Planning Time: 0.369 ms Execution Time: 2939.455 ms
2.9 秒
表
clicks
包含 35m 行,表revenue
包含 56m 行。伺服器是 linode 32gb 16 核 ubuntu。我對此做了什麼?
它對我來說是 mysql,但之前沒有處理過這些數據。我一直在研究提高這個數據庫的性能。我一直在調整 postgres 的性能。有 0 個改進(
work_mem,shared_buffers
)並嘗試理解我不太擅長的查詢解釋器。我正在考慮表分區/物化視圖,但我也讀過表分區可能無效。或者調整這個查詢會帶來至少 50% 的性能提升?由於這些表將來會堆積更多,克服這個問題的理想方法是什麼?
Postgres 版本:
PostgreSQL 11.5 (Ubuntu 11.5-1.pgdg16.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609, 64-bit
Postgres 設置:
max_connections = 200 shared_buffers = 8GB effective_cache_size = 24GB maintenance_work_mem = 2GB checkpoint_completion_target = 0.7 wal_buffers = 16MB default_statistics_target = 100 random_page_cost = 1.1 effective_io_concurrency = 200 work_mem = 5242kB min_wal_size = 1GB max_wal_size = 2GB max_worker_processes = 16 max_parallel_workers_per_gather = 8 max_parallel_workers = 16
到目前為止有幫助的事情(從〜10-15s到〜2-4s):
- 將 Postgres 從升級
9.5
到11.5
(允許並行化,也可能有其他好處)- 去除不必要的
DISTINCT
一些進一步的想法:
- 研究如何允許 Postgres 選擇僅索引掃描,而不是最慢的索引掃描花費最多時間(注意,多列索引的列順序至關重要)。
- 如果您可以鼓勵使用散列或合併連接來代替嵌套循環,它們可能會更快。這些列的更好的統計數據可能會有所幫助,甚至可能是多變數的。它目前低估了 4 倍的行數,因此可能會選擇具有更好資訊的不同計劃。值得注意的是,您可能還需要額外的排序索引來啟用合併連接。有關擴展統計資訊和加入操作的更多資訊。
此外,還有一些工具可以讓您更輕鬆地理解和共享查詢執行計劃。
免責聲明:我在最新列出的 pgMustard 上工作。