Ghan
12월 24, 2020, 4:19오전
21
실제로 업데이트되는 랭킹이 몇 개든 상관없이, 전체 게시글 테이블에 걸쳐 모든 주제에 대한 랭킹을 계산하기 위해 서브쿼리를 실행해야 합니다.
이 서브쿼리를 실행하는 데 약 40초가 걸리며, WHERE 절에 도달하기도 전에 조인을 위해 반복 실행되어야 하는 중첩 루프 안에 있습니다. 이것이 쿼리 비용을 폭증시키는 원인으로 보입니다.
SELECT id, percent_rank()
OVER (PARTITION BY topic_id ORDER BY SCORE DESC) as percent_rank
FROM posts
1개의 좋아요
Ghan
12월 24, 2020, 5:16오후
22
코드를 살펴본 후 이제 이해했습니다. 이 쿼리는 랭크 업데이트가 필요한 모든 게시물을 처리할 때까지 반복적으로 실행되므로, SQL 프로세스를 관찰하던 중 한 실행이 끝나고 다른 실행이 시작되는 과정을 시간 단위로 여러 번 확인했습니다.
그러나 LIMIT가 쿼리의 복잡성에 실제로는 그렇게 큰 도움이 되지 않는 것 같습니다. 사실, limit을 200000으로 증가시키면 쿼리 플랜이 상당히 개선되는 것을 발견했습니다.
20000일 때 비용이 거의 2억에 달하는 거대한 nested loop를 볼 수 있습니다:
-> 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개의 좋아요