복잡한 쿼리가 아닌데 속도가 느려 실행계획을 보니 좀 이해할 수 없는 실행계획이 나와서요.
아래와 같이 가수, 앨범, 곡 3개의 테이블이 1:N 의 fk 를 갖고 있습니다.
ARTIST (
id int4 pk,
name varchar(255)
)
ALBUM (
id int4 pk,
title varchar(255),
artist_id int4 fk,
reg_date timestamp (index)
)
SONG (
id int4 pk,
title varchar(255),
album_id int4 fk
)
최근 등록된 앨범 10개의 앨범이름, 가수이름, 수록곡수를 갖고오는 간단한 쿼리입니다.
SELECT
ARTIST.name,
ALBUM.title,
(SELECT COUNT(id) FROM SONG WHERE album_id = ALBUM.id) AS track_num
FROM
ALBUM, ARTIST
WHERE
ALBUM.artist_id = ARITST.id
ORDER BY
ALBUM.reg_date DESC
LIMIT 10;
저는 당연히 ALBUM.reg_date 인덱스를 타고 10개를 갖고온후
ALBUM.artist_id = ARTIST.id 를 index scan 10번하고 track_num 을 구하기 위해 10번 서브쿼리가 돌아갈것을 기대했습니다.
그런데 실제 실행계획은 모든 앨범에 대해서 track_num 을 구하고 (그나마 다행히 SONG_IDX_ALBUM_ID를 사용해서)
ARTIST 도 pk 가 아닌 seq scan 을 해서 갖고오고 있습니다.
cost도 300만을 훌쩍 넘기고요 (물론 실제 수행시간은 0.3 초정도로 기지는 않습니다.)
postgresql , 너가 알아서 했겠지,, 라고 넘어가려다
SELECT
ARTIST.name,
(SELECT COUNT(id) FROM SONG WHERE album_id = A.id) AS track_num
FROM
(SELECT id, title FROM ALBUM ORDER BY reg_date DESC LIMIT 10) AS A,
ARTIST
WHERE
ALBUM.artist_id = ARTIST.id
와 같이 FROM 안에 A 라는 서브쿼리로 먼저 뽑아내도록 했더니 1000 이하의 낮은 cost가 계산되고
수행시간도 0.04초 이하로 팍 떨어집니다.
검색등으로 인해 쿼리가 동적으로 점점 복잡해지기때문에 후자처럼 사용하기가 힘든데
방법이 없을까요?
제가 더 공부해야하는지, 나름 맹신하는 postgresql 이 아직 더 성숙해야하는지.
제가 부족한거면 좋겠다는 생각으로 고수님들의 조언을 구합니다.
|