어떤 DBMS 든지 쿼리의 실행 계획을 수립하는 옵티마이저는 가장 복잡한 부분으로 알려져 있으며, 옵티마이저가 만들어 내는 실행 계획을 이해하는 것 또한 상당히 어려운 부분이다. 하지만 그 실행 계획을 이해할 수 있어야만 실행 계획의 불합리한 부분을 찾아내고, 더욱 최적화된 방법으로 실행 계획을 수립할 수 있도록 유도할 수 있다.

6.1.1 쿼리 실행 절차

MySQL 서버에서 쿼리가 실행되는 과정은 크게 3가지로 나눌 수 있다.

  1. 쿼리문 세분화(SQL Parsing) : 사용자로부터 요청된 SQL 문장을 잘게 쪼개서 MySQL 서버가 이해할 수 있는 수준으로 분리한다.
  2. 최적화 및 실행 계획 수립 : SQL 의 파싱 정보(파스 트리)를 확인하면서 어떤 테이블부터 읽고 어떤 인덱스를 이용해 테이블을 읽을지 선택한다.
  3. 실행 : 두 번째 단계에서 결정된 테이블의 읽기 순서나 선택된 인덱스를 이용해 스토리지 엔진으로부터 데이터를 가져온다.

첫번째 단계와 두번째 단계는 거의 MySQL 엔진에서 처리하며, 세번째 단계는 MySQL 엔진과 스토리지 엔진이 동시에 참여해서 처리한다.

8FA31BA1-41AB-4DB9-9A04-D3B9932ABF1D.jpeg

6.1.2 옵티마이저의 종류

옵티마이저는 데이터베이스 서버에서 두뇌와 같은 역할을 담당하고 있다. 옵티마이저는 현재 대부분의 DBMS 가 선택하고 있는 비용 기반 최적화(Cost-based optimizer, CBO) 방법과 예전 오라클에서 많이 사용됐던 규칙 기반 최적화(Rule-based optimizer, RBO) 방법으로 크게 나눠볼 수 있다.

규칙 기반 최적화는 각 테이블이나 인덱스의 통계 정보가 거의 없고, 상대적으로 느린 CPU 연산 탓에 비용 계산 과정이 부담스러웠기 때문에 사용되던 최적화 방법이다. 현재는 거의 대부분의 RDBMS 가 비용 기반 옵티마이저를 채택하고 있으며, MySQL 역시 마찬가지다.

6.1.3 통계 정보

비용 기반 최적화에서 가장 중요한 것은 통계 정보다. 통계 정보가 정확하지 않다면 전혀 엉뚱한 방향으로 쿼리를 실행해 버릴 수 있기 때문이다.

MySQL 또한 다른 DBMS 와 같이 비용 기반의 최적화를 사용하지만 다른 DBMS 보다 통계 정보는 그리 다양하지 않다. 기본적으로 MySQL 에서 관리되는 통계 정보는 대략의 레코드 건수와 인덱스의 유니크한 값의 개수 정도가 전부다. 오라클과 같은 DBMS 에서는 통계 정보가 상당히 정적이고 수집에 많은 시간이 소요되기 때문에 통계 정보만 따로 백업하기도 한다. 하지만 MySQL 에서 통계 정보는 사용자가 알아채지 못하는 순간순간 자동으로 변경되기 때문에 상당히 동적인 편이다. 하지만 레코드 건수가 많지 않으면 통계 정보가 상당히 부정확한 경우가 많으므로 ANALYZE 명령을 이용해 강제적으로 통계 정보를 갱신해야 할 때도 있다.