MySQL 을 비롯한 RDB 들은 쿼리를 던지면 옵티마이저를 통해 가장 효율적인 쿼리 플랜을 생성하여 해당 방식으로 쿼리를 수행한다.
예를 들면 다음과 같은 테이블이 있다고 할 때,
create table delivery
(
id int unsigned auto_increment primary key,
seller_id int unsigned,
order_id int unsigned,
status varchar(50),
send_date_time datetime(6),
)
datetime field 인 send_date_time를 기준으로 조회해보자. 인덱스는 걸려있다.
SELECT * FROM delivery WHERE send_date_time < $send_date_time;
보이는 것 처럼 이번에도 인덱스를 사용한다.
여기까지는 너무 당연하다.
이번에는 send_date_time를 기준으로 조회하고, id로 정렬해보자.
아마도 배송일자 기준으로 조회하고, 먼저 생성된 레코드 부터 처리하는 유스케이스에 사용될 것이다.
SELECT * FROM delivery WHERE send_date_time < $send_date_time ORDER BY id;
그런데 이렇게 조회하면 아래와 같이 인덱스를 타지 않고 PK 정렬을 먼저 하는 쿼리 플랜을 보여준다.
조회 조건으로 들어간 날짜가 현재 시간에 가까울 수록 아래와 같은 쿼리 플랜을 생성할 가능성이 높은듯 하다.
이러한 경우 인덱스를 타지 않기 때문에 성능이 크게 달라질 수 있어 유의해야 한다.
해결 방법은, 인덱스를 사용하도록 아래와 같이 직접 명시하는 방법이 있다.
SELECT *
FROM delivery
use index (delivery_send_date_time_index)
WHERE send_date_time < $send_date_time
ORDER BY id;
또한 애초에 pk를 정렬 조건으로 쓰는게 맞는지 한 번 더 고민해 봐야할 것 같다.
이번 케이스는 reg_date_time 등을 추가해서 레코드 생성 시점을 별도로 관리하는 것이 더 적합했던 것 같다.
id를 주로 sequential 하게 사용하지만, 때에 따라 uuid등으로 사용할 수도 있으니 말이다.
'SQL' 카테고리의 다른 글
Postgres - sorry, too many client already (0) | 2023.03.27 |
---|