Ghan
21
无论实际要更新多少个排名,它仍然必须运行子查询来计算整个 posts 表中每个主题的排名。
这个子查询大约需要 40 秒才能运行,而且它位于一个嵌套循环内部,该循环必须在进入 WHERE 子句之前为连接操作执行。这似乎就是导致查询成本激增的原因。
SELECT id, percent_rank() \n OVER (PARTITION BY topic_id ORDER BY SCORE DESC) as percent_rank \nFROM posts
1 个赞
Ghan
22
我查看了代码,现在明白了。这个查询会反复执行,直到清除所有需要更新排名的帖子。因此,当我观察 SQL 进程时,在数小时内看到该查询多次运行,每完成一次运行后紧接着开始下一次。
不过,LIMIT 似乎并没有显著降低查询的复杂度。事实上,我发现如果将 LIMIT 增加到 200000,查询计划反而会有显著改善。
当 LIMIT 为 20000 时,我看到的嵌套循环成本接近 2 亿:
-> Nested Loop (cost=6033694.44..190270554.32 rows=26680560 width=16)
如果我将 LIMIT 直接增加到 200000,生成的查询计划看起来就干净多了:
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------
Update on posts (cost=7334394.89..8873863.82 rows=200000 width=833)
-> Nested Loop (cost=7334394.89..8873863.82 rows=200000 width=833)
-> Subquery Scan on x (cost=7334394.45..7370147.82 rows=200000 width=48)
-> Limit (cost=7334394.45..7368147.82 rows=200000 width=12)
-> Hash Join (cost=7334394.45..11837188.36 rows=26680560 width=12)
Hash Cond: (posts_1.id = y.id)
Join Filter: ((posts_1.percent_rank IS NULL) OR (y.percent_rank <> posts_1.percent_rank))
-> Hash Join (cost=35403.20..2845221.73 rows=26703700 width=12)
Hash Cond: (posts_1.topic_id = topics.id)
-> Seq Scan on posts posts_1 (cost=0.00..2739721.00 rows=26703700 width=16)
-> Hash (cost=23918.11..23918.11 rows=918807 width=4)
-> Index Only Scan using topics_pkey on topics (cost=0.42..23918.11 rows=918807 width=4)
-> Hash (cost=6834805.00..6834805.00 rows=26703700 width=12)
-> Subquery Scan on y (cost=6033694.00..6834805.00 rows=26703700 width=12)
-> WindowAgg (cost=6033694.00..6567768.00 rows=26703700 width=24)
-> Sort (cost=6033694.00..6100453.25 rows=26703700 width=16)
Sort Key: posts_2.topic_id, posts_2.score DESC
-> Seq Scan on posts posts_2 (cost=0.00..2739721.00 rows=26703700 width=16)
-> Index Scan using posts_pkey on posts (cost=0.44..7.52 rows=1 width=789)
Index Cond: (id = x.id)
JIT:
Functions: 30
Options: Inlining true, Optimization true, Expressions true, Deforming true
(23 rows)
我不确定是什么导致了这种切换。在我们刚完成的大规模导入之后,至少暂时提高这个限制可能是值得的,以便尽快清理积压任务。
2 个赞