AWS Aurora Databsae의 Parallel Query에 대한 개념을 이해하고, 데이터베이스의 성능을 향상 시키는 방법에 대해서 알아 봅니다.
AWS Aurora Database Parallel Query 활성화 방법 및 특징
Author : Sungwook Kang(강성욱), AWS Solutions Architect
Amazon Aurora MySQL 병렬 쿼리는 데이터 집약적인 쿼리 처리에 수반되는 I/O 및 컴퓨팅의 일부를 병렬화 하는 최적화 작업 입니다. 병렬화되는 작업은 스토리지로부터 행 검색, 열 값 추출, 어떤 행이 WHERE 절 및 JOIN절의 조건과 일치하는지 판단 합니다. 데이터 집약적인 작업은 Aurora 분산 스토리지 계층의 여러 노드에 위임(푸시다운)되고 병렬 쿼리가 없으면 각 쿼리가 스캔한 모든 데이터를 Aurora MySQL 클러스터(헤드노드)내의 단일 노드로 가져오고 거기에서 모든 쿼리 처리를 수행 합니다. 병렬 쿼리 기능을 설정하면 Aurora MySQL 엔진이 힌트 또는 테이블 속성과 같은 SQL의 변경 필요 없이 쿼리에 따라 자동으로 병렬화 여부를 판단 합니다.
데이터베이스를 생성할 때 [Engine Version]에서 [Hide filters]를 확장하여 parallel query 기능을 활성화할 수 있습니다.
기본적으로, 병렬 쿼리를 사용하지 않을 경우 Aurora 쿼리에 대한 처리는 원시 데이터를 Aurora 클러스터 내 단일 노드(헤드 노드)로 전송 합니다. 그런 다음 Aurora는 해당 단일 노드의 단일 스레드에서 해당 쿼리에 대해 추가되는 모든 처리를 수행 합니다. 병렬 쿼리를 사용할 경우, 이러한 I/O 집약적이고 CPU 집약적인 작업의 대부분이 스토리지 계층의 노드로 위임 됩니다. 행은 이미 필터링 되고 열 값은 이미 추출되어 전송된 상태로, 결과 집합의 간소화된 행만 다시 헤드 노드로 전송 됩니다. 성능 혜택은 네트워크 트래픽의 감소, 헤드 노드에서 CPU 사용량의 감소, 및 스토리지 노드 전체에서 I/O 병렬화로부터 비롯됩니다. 병렬 I/O, 필터링 및 프로젝션의 양은 쿼리를 실행하는 Aurora 클러스터의 DB 인스턴스 수와 무관 합니다.
아래는 위에서 설명한 병렬 쿼리 사용의 장점을 목록으로 정리한 것 입니다.
- 여러 스토리 노드에 걸친 물리적 읽기 요청을 병렬화 하여 I/O 성능 개선
- 네트워크 트래픽 감소 : Aurora는 전체 데이터 페이지를 스토리지 노드로부터 헤드 노드로 전송한 다음 그 후에 불필요한 행과 열을 필터링 하지 않고 결과 집합에 필요한 열 값만 포함된 간소화된 튜플을 전송.
- 푸시 다운, 행 필터링 및 WHERE 절에 대한 열 프로젝션으로 인한 헤드 노드에 대한 CPU 사용량 감소.
- 버퍼 풀에서의 메모리 압력 감소 : 병렬 쿼리에 의해 처리된 페이지는 버퍼풀에 추가되지 않으므로 데이터 집약적인 스캔 중 버퍼 풀에서 자주 사용되는 데이터가 제거될 가능성이 감소.
- 기존 데이터에 대한 장기 실행 분석 쿼리 수행이 유용해진 덕분에 추출, 변환, 로드(ETL) 파이프라인에서 데이터 중복의 잠재적 감소.
Aurora MySQL 병렬 쿼리의 아키텍처는 다른 데이터베이스 시스템에서 이름이 유사한 기능의 아키텍처와 다릅니다. Aurora MySQL 병렬 쿼리는 SMP(Symmetric Multi Processing)를 포함하지 않아, 데이터베이스의 CPU 용량에 의존하지 않습니다. 병렬 처리는 쿼리 조정자 역할을 하는 Aurora MySQL 서버와는 독립적인 스토리지 계층에서 적용됩니다.
Aurora MySQL에서 병렬 쿼리를 사용하기 위해서는 몇 가지 사전 조건 및 제한 사항이 있습니다. 해당 내용은 버전에 따라 지원되는 내용이 다르고, 향후 버전 업데이트에 따라 변경될 가능성이 크기 때문에 자세한 내용은 아래 링크의 내용을 직접 참고할 수 있도록 합니다.
Aurora MySQL 3 (MySQL 8.X) 버전 부터는 해시조인(Hash Join)이 기본적으로 설정되어 있습니다. optimizer_switch 구성 설정의 block_nested_loop 플래그를 사용하여 설정을 비활성화 할 수 있습니다. Aurora MySQL 3버전에서는 Aurora_disable_hash_join 옵션은 사용되지 않습니다.
Aurora MySQL 1.23 또는 2.09 이상 버전에서는 병렬 쿼리 및 해시 조인 설정이 기본적으로 해제되어 있습니다. 이 부분을 활성화하기 위해서는 클러스터 구성 파라메터 aurora_disable_hash_join=OFF로 설정 합니다.
버전 1.23 이전의 Aurora MySQL 5.6 호환 클러스터의 경우 해시 조인은 병렬 쿼리 클러스터에서 항상 사용할 수 있습니다. 이 경우 해시 조인 기능에 대해 어떤 작업도 수행할 필요가 없습니다. 이러한 클러스터를 버전 1 또는 버전 2의 상위 릴리스로 업그레이드하는 경우 해시 조인도 설정해야 합니다.
병렬 쿼리를 사용하려면 테이블 속성이 ROW_FORMAT=Compact 또는 ROW_FORMAT=Dynammic 설정을 사용해야하기 때문에 INNODB_FILE_FORMAT 구성 옵션에 대한 변경 사항이 있는지 확인해야 합니다. 옵션을 변경할 때에는 항상 변경 전후에 대한 성능 문제가 발생할 수 있으므로 반드시 워크로드 테스트를 진행할 수 있도록 합니다.
앞에서도 언급하였지만 병렬 쿼리를 이용하기 위해 어떤 특별한 조치를 수행할 필요는 없습니다. 필수적 요구사항을 충족한 후에는 쿼리 옵티마이저가 각 특정 쿼리에 대하여 병렬 쿼리를 사용할지 여부를 자동으로 결정하기 때문입니다. 쿼리가 실행될 때 병렬 쿼리로 실행되었는지 유무는 EXPLAIN 명령을 실행하여 실행계획을 통해 확인할 수 있습니다.
아래 예시는 해시 조인이 설정되어 있지만 병렬 쿼리가 해제되어 있어 병렬 쿼리가 아닌 해시 조인으로 실행계획이 표시 되었습니다.
병렬 쿼리가 설정된 후에는 해시 조인 실행 시 parallel query 라고 표시된 것을 확인할 수 있습니다.
Aurora MySQL 클러스터가 병렬 쿼리를 실행할 때 버퍼풀을 사용하지 않기 때문에 VolumeReadIOPS 값이 증가할 수 있습니다. 따라서 쿼리는 빠르기 실행되지만 이렇게 최적화된 프로세싱은 읽기 작업 및 관련 비용을 증가시킬 수 있습니다. 병렬 쿼리 모니터링에 대한 카운터는 아래 링크에서 “병렬 쿼리 모니터링” 섹션을 참고할 수 있도록 합니다. 카운터는 DB 인스턴스 수준에서 추적 됩니다. 서로 다른 엔드포인트로 연결된 경우 각 DB 인스턴스가 자체의 고유한 병렬 쿼리 집합을 실행하기 때문에 서로 다른 지표가 표시될 수도 있습니다. 또한 리더 엔드포인트가 각 세션마다 서로 다른 DB 인스턴스에 연결된 경우에도 서로 다른 지표가 표시될 수도 있습니다.
병렬 쿼리는 InnoDB 테이블에만 적용됩니다. Aurora MySQL에서는 임시 테이블 사용시, 임시 저장소로 MyISAM을 사용하기 때문에 임시 테이블을 포함하는 내부 쿼리 단계에서는 병렬쿼리를 사용하지 않습니다. 그리고 실행 계획으로는 Using temporary라고 표시됩니다.
(MySQL 8.0 부터는 임시 테이블이 디스크에 저장될 때 InnoDB 스토리지를 사용하도록 개선되어 있습니다.)
Reference