MySQL LIMIT + Offset 쿼리 성능 문제

Posted by 엘키의 주절 주절 on October 5, 2018

페이징 처리시 자주 사용되는 Offset. 단순히 쿼리로 OFFSET을 수행하면 성능 저하가 일어난다.

offset 사용시 성능 저하 이슈에 대해 검토와 관련 글들

이를 확인하기 위해 DB에서 직접 쿼리를 날려 보자 (속도 차가 나는 것은 실제 사용 쿼리보다 좀 더 단순한 쿼리로 비교했기 때문임) 30만건 이상의 데이터를 넣어둔 테이블에서의 결과임을 밝혀둔다.

1
2
3
SELECT * FROM 테이블
order by project_name asc
LIMIT 10 OFFSET 300000;

default_limit_offset

3.2초
Full Table Scan이 일어남 (전체 데이터 건수에 대한 접근)
그리고, 그 데이터들을 모두 정렬하는 과정의 코스트가 많이 발생함.

1
2
3
4
5
SELECT * 
FROM 테이블 as p
JOIN (SELECT 키값 
    FROM   테이블
    ORDER  BY 정렬컬럼 LIMIT 300000, 10) AS t ON t. = p.; 

tuning_limit_offset

0.641초
Full Index Scan이 일어난 뒤, 인덱스를 정렬함.
정렬된 데이터를 기준으로 Unique Key Lookup 기반의 Nested Loop 처리로 인한 성능 향상

인덱스 구조 관련 팁

  • LIMIT OFFSET 에서 사용하는 Sorting 값이 있다면, 해당 값을 Clustering Index로 잡으면 성능 이득을 더 크게 볼 수 있다.
  • Sort 과정을 건너뛰어도 되는 만큼 처리할 데이터양이 많거나 클수록 차이가 나는 부분이니, 페이징할 데이터 양이 큰 경우 검토할 여지가 있다.