SELECT DISTINCT, 인덱스가 완벽해도 전체 행을 스캔한다
- Postgres의 SELECT DISTINCT는 인덱스를 어떻게 짜든 예측 조건에 맞는 모든 행을 스캔함. 실행 시간이 고유값 개수가 아니라 매칭 행 수에 따라 늘어남.
- DBOS의 파티션 큐 워크로드에서 활성 파티션을 찾는 이 쿼리가 가장 비싼 질의였음. 파티션 10개를 고정하고 파티션당 행을 100에서 1M까지 늘린 벤치마크에서 지연시간이 행 수에 선형으로 증가함.
- Postgres 질의 계획은 풀 인덱스 스캔을 선택해 1M 개 ENQUEUED 워크플로를 모두 읽고 겨우 3개 파티션 키를 찾아냄. 읽은 1M 행은 전부 낭비였음.
- 파티션이 몇 개뿐인데 각 파티션에 워크플로가 쌓인 좁고 깊은 워크로드에선 쿼리가 1ms도 안 걸릴 것으로 예상했으나 실제로는 수 초가 걸림.
- 파티션이 많고 파티션당 워크플로가 적은 넓고 얕은 워크로드에선 같은 쿼리가 예상대로 동작해 문제가 드러나지 않았음.
Hacker News opinions
결론은 맞는데 이건 이미 문서에 있는 내용임. DISTINCT는 결과를 먼저 정렬하거든. GROUP BY도 몰랐고 인덱스도 ANALYZE도 몰랐던 것 같음. Postgres 18의 새 skip scan 인덱싱이 도움이 될 수도 있고.
GROUP BY 쓰면 이게 해결되나? skip scan은 여기서 아무 역할도 안 한다고 글에 써 있음. 그리고 인덱스랑 질의 계획은 글에서 잔뜩 다루는데?
글을 읹긴 읽은 거냐? 쿼리에 완벽한 인덱스를 만들어 줬는데도 DISTINCT에는 skip scan이 안 쓰인다고 나옴.
Loose index scan이 정확히 이걸 위한 거임. MySQL 8.0에는 있고 Postgres에는 아직 없음.
그거 글에 써 있음. 이제는 그렇더라.
회사 공동창업자가 Postgres 창시자라는 게 솔직히 안 믃김. 새 내용이 하나도 없고 그냥 자기들이 직접 겪은 발견 수준임. 이런 쿼리는 어떻게 해도 안 커지는데, 이미 많이 투자했으면 DBA를 고용하고, 아직 초기면 데이터 모델링할 아키텍트를 고용하는 게 낫음.
안 커진다는 게 뭘로 스케일한다는 거임? 인덱스에 고유값 m개 있으면 이렇게 뽑는 데 m log(n)이면 데이터가 아무리 많아도 대부분 케이스에서 충분함.
그 사람 Stonebraker임. 필요 없는 사람한테 뭐 파는 전력이 있음.
난 요즘 SELECT DISTINCT 쓰이면 경고 신호로 본음. 유니크 제약을 제대로 못 짜서 뒤늦게 중복을 제거하려는 사람, join 조건 빠뜨린 사람, 한 번 효과 봤다고 도처에 다는 사람까지.
전체 row 비슷한 대상에 쓰면 확실히 경고 신호인데. 이 글 상황은 좀 다르지 않나?
DISTINCT 쓰지 말라는 충고는 예전부터 계속 있었는데, AI 시대에 와서 그 상식이 통째로 사라진 느낌임.
수동 우회로 질의 계획을 강제하는 게 답이라면, Postgres가 그 더 나은 계획을 알아서 짜게 해줘야지. 이게 프로젝트 안에 들어가 있어야 함.