작성
·
151
·
수정됨
1
제가 선생님 강의를보고
테이블에 천만개의 데이터를 넣고 인덱스를 테스트하고있었는데요,
2가지 질문이 생겼습니다.
질문
다음과 같이 익스플레인 에널라이즈를 하면 소요시간이 약 704ms 으로 나옵니다.
그런데 익스플레인 에널라이즈만 제거하고 다시 셀렉트를 하면 소요시간이 1.494로 증가하는데
단순 조회 쿼리와 익스플레인 에널라이즈 쿼리가 서로 다르게 동작해서 그런건가요?
분석때문에 에널라이즈쪽이 더 오래걸릴까 싶었는데 오히려 반대라서 왜 이런현상이 발생하는지 궁금합니다.
-> Filter: ((reservation.userId = 389788) or (reservation.seatId = 50)) (cost=11192 rows=10272) (actual time=2.33..678 rows=10271 loops=1)
-> Deduplicate rows sorted by row ID (cost=11192 rows=10272) (actual time=2.3..676 rows=10271 loops=1)
-> Index range scan on reservation using idx_user over (userId = 389788) (cost=1.11 rows=1) (actual time=0.115..0.115 rows=0 loops=1)
-> Index range scan on reservation using idx_seat over (seatId = 50) (cost=1038 rows=10271) (actual time=0.0497..2.77 rows=10271 loops=1)
질문
제가 다음과 같은 쿼리에 인덱스를 걸며 테스트해보니
복합인덱스 ( userId,seatId or reverse ) 는 전혀 인덱스를 활용하지않고 단일 인덱스를 각각 지정했을 경우에만 아래와같이 인덱스를 병합해서 사용하더라구요. 이렇게 속도를 절반으로 떨어뜨렸는데 아무래도 데이터가 천만개라 그런가 여전히 1초 이상의 시간이 소요되어서 선생님이 보셨을때 여기서 더 개선해볼 방법이 있는지 궁금합니다.
where쪽을 건드려 보자니 둘중 하나라도 충족되면 가져와야하는 상황이라면 or 말고 다른건 떠오르질않았습니다.
(에널라이즈는 시간이 1초 미만으로 나오지만 실제로 쿼리 돌려보면 소요시간 1.4초 이상으로 찍힙니다. )
CREATE INDEX idx_user ON reservation_entity(userId);
CREATE INDEX idx_seat ON reservation_entity(seatId);
SELECT
`reservation`.`createdAt` AS `reservation_createdAt`,
`reservation`.`updatedAt` AS `reservation_updatedAt`,
`reservation`.`deletedAt` AS `reservation_deletedAt`,
`reservation`.`id` AS `reservation_id`,
`reservation`.`userId` AS `reservation_userId`,
`reservation`.`concertId` AS `reservation_concertId`,
`reservation`.`seatId` AS `reservation_seatId`,
`reservation`.`status` AS `reservation_status`,
`reservation`.`price` AS `reservation_price`,
`reservation`.`concertName` AS `reservation_concertName`,
`reservation`.`seatNumber` AS `reservation_seatNumber`,
`reservation`.`openAt` AS `reservation_openAt`,
`reservation`.`closeAt` AS `reservation_closeAt`
FROM
`reservation_entity` `reservation`
WHERE
`reservation`.`userId` = 389788
OR `reservation`.`seatId` = 50;
-> Filter: ((reservation.userId = 389788) or (reservation.seatId = 50)) (cost=11192 rows=10272) (actual time=2.33..678 rows=10271 loops=1)
-> Deduplicate rows sorted by row ID (cost=11192 rows=10272) (actual time=2.3..676 rows=10271 loops=1)
-> Index range scan on reservation using idx_user over (userId = 389788) (cost=1.11 rows=1) (actual time=0.115..0.115 rows=0 loops=1)
-> Index range scan on reservation using idx_seat over (seatId = 50) (cost=1038 rows=10271) (actual time=0.0497..2.77 rows=10271 loops=1)
답변 1
0
안녕하세요 alopp님! 좋은 질문 해주셨네요👍😊
하나씩 답변 드려보겠습니다.
저도 이 부분은 왜 그런지 궁금해서 검색을 좀 해봤어요! 확실하진 않지만 추측하고 알게 된 정보를 알려드려 볼게요!
일반적으로는 EXPLAIN ANALYZE가 분석을 같이하기 때문에 시간이 더 오래걸리는 경우가 많습니다. 하지만 EXPLAIN ANALYZE를 처리할 때 내부적으로 실제 Query를 실행시키지 않고 추정(샘플링)을 통해 조금 더 효율적으로 처리를 할 수도 있다고 합니다! 이런 이유로 인해 EXPLAIN ANALYZE로 처리했을 때 응답 시간이 더 작게 나올 수도 있습니다.
복합 인덱스를 활용하지 않은 이유는 WHERE문에서 AND가 아닌 OR 조건을 활용했기 때문입니다. 그리고 인덱스를 활용했음에도 불구하고 시간이 오래 걸리는 이유는 최종적으로 반환하는 데이터 개수가 많아서 오래 걸린다고 예상할 수 있습니다. 그리고 많은 데이터들을 가지고 Deduplicate 작업을 함으로써 시간이 오래 걸린 것으로 예상되네요!
이 외로 궁금하신 점 있으시면 편하게 질문 또 남겨주세요~~~