https://stackoverflow.com/questions/10379956/parsing-sql-like-syntax-design-pattern
SQL Parser가 쿼리를 트리 구조로 파싱한다.
옵티마이저가 트리를 참고해 어떤 테이블부터, 어떤 인덱스를 이용해 테이블을 읽을지 선택한다.
→ 실행 계획 만들어진다.
실행 계획대로 스토리지 엔진에서 데이터를 가져온다.
옵티마이저의 종류에는 비용 기반 최적화와 규칙 기반 최적화가 있다.
예전에는 규칙 기반 최적화가 많이 사용되었다. 규칙 기반 최적화는 옵티마이저의 우선순위에 따라 쿼리를 처리하기 때문에 같은 쿼리는 항상 같은 실행 계획에 의해 처리된다.
데이터의 종류가 다양해지면서 데이터 양과 분포도가 다양해지면서 상황에 맞는 최적화 방법이 필요해졌다. 비용 기반 최적화는 다양한 방법을 만들고, 각 단위 작업의 비용 정보와 대상 테이블의 통계 정보를 이용해 실행 계획별 비용을 산출한다. 이중에서 비용이 최소로 소요되는 처리 방식을 선택해 쿼리를 실행한다.
Chat GPT 답변
RDBMS에는 데이터를 정렬하거나 그루핑하는 등의 기본 데이터 가공 기능을 가지고 있다.
테이블 레코드 수가 너무 작아서 인덱스보다 풀 테이블 스캔이 빠른 경우
인덱스 레인지 스캔을 사용하더라도 선택도가 너무 낮아(=인덱스 컬럼에 중복값이 많아) 조건 일치 레코드 건수가 너무 많은 경우
WHERE 절이나 ON 절에 인덱스를 이용할 수 있는 적절한 조건이 없는 경우(?)
풀 테이블 스캔 최적화
Read ahead : 페이지를 읽으면 다음 페이지를 예측해 미리 메모리에 로딩한다.
초반에는 포그라운드 스레드가 페이지 읽기를 실행하지만 나머지 페이지는 백그라운드 스레드가 읽기를 넘겨 받고, 읽은 데이터를 버퍼 풀에 저장한다.
포그라운드 스레드는 버퍼풀에 있는 데이터를 읽기만 하면 되므로 쿼리 처리가 빨라진다.
풀 인덱스 스캔 최적화
인덱스 테이블에서 처리
SELECT COUNT(*) FROM employees;
1,SIMPLE,employees,,index,,PRIMARY,4,,299468,100,Using index
SELECT * FROM employees;
1,SIMPLE,employees,,ALL,,,,,299468,100,
innodb_parallel_read_threads
인덱스를 이용하는 방법
쿼리가 실행될 때 Filesort라는 별도의 처리를 이용하는 방법
Explain : Extra 컬럼 Using filesort
인덱스 이용 장점
인덱스 이용 단점
filesort 장점
filesort 단점
sort_merge_passes
에 누적된다<sort key, rowid>
👉🏻 Two-pass : 정렬에 필요한 컬럼만 가져와 정렬하고 다시 메모리에서 나머지 컬럼들을 조회해오는 방식 / 작업에 두 단계가 필요하다.
<sort key, additional_fields> : 레코드 컬럼들 고정 사이즈로 메모리에 저장
<sort_key, packed_additional_fields> : 레코드 컬럼들 가변 사이즈로 메모리에 저장
👉🏻 Single-pass / 아예 들고와서 정렬 후 바로 결과 리턴 / 한 단계만 필요하다.
→ Trade-off : 소트 버퍼 공간이 더 필요하다 / 적은 레코드일 경우 빠름
max_length_for_sort_data
< 레코드 크기밑으로 갈수록 처리 속도는 떨어진다.
인덱스 | - |
---|---|
조인에서 드라이빙 테이블만 정렬 | using filesort |
조인 결과를 임시 테이블로 저장 후 정렬 | using temparary; using filesort |
🔺 조건
col
, ORDER BY col
두 컬럼이 같은 인덱스를 사용할 수 있어야 한다.🔺 조건