MySQL 에서 데이터를 압축해서 디스크에 저장하는 것은 쿼리 성능뿐만 아니라 백업 및 복구 시간까지 영향을 미친다. 데이터 압축이 어떻게 이루어지는지 살펴보자.
더티 페이지를 디스크에 쓰는 시점에 압축해서 저장하고, 버퍼 풀로 읽어 올 때 해제해서 페이지 단위로 압축을 사용하는 방식이다.
페이지는 동일한 크기로 사용되어야 하는데 페이지 압축 방식을 사용하면 파일의 크기를 가늠할 수 없는 문제가 발생한다. 이를 보완하기 위해 압축으로 줄인 부분을 펀치 홀(Punch hole) 공간으로 사용하는 방식으로 보완한다. 펀치 홀 방식이란 16KB 페이지가 7KB로 압축되었을때, 줄여진 9KB 만큼을 펀치 홀 공간으로 두어 디스크에는 16KB를 저장하듯이 동작하지만 실제로 디스크에서는 7KB의 공간만 차지하는 방식이다.
펀치 홀 방식은 MySQL 서버를 실행하는 운영체제뿐만 아니라 하드웨어 레벨에서도 지원해야하는 기능이기 때문에 많이 사용되지는 못한다.
테이블 압축은 운영체제, 하드웨어 제약 없이 사용할 수 있어 일반적으로 더 많이 사용된다.
하지만 테이블 압축을 적용하면 다음과 같은 단점들이 있다.
버퍼 풀 공간 활용률이 낮아짐 - Unzip_LRU
쿼리 처리 성능이 낮아짐 - 압축, 압축해제의 CPU 연산 및 버퍼 풀 활용률이 낮음
데이터를 자주 변경할 경우 압축률이 낮아짐 - 압축 패턴이 깨짐
압축 테이블 생성
별도의 테이블 스페이스에서 innodb_file_per_table 시스템 변수를 ON으로 설정한다.
CREATE TABLE 명령에서 KEY_BLOCK_SIZE=4, 8 등을 설정하여 테이블 페이지를 어느 사이즈로 압축할지 설정한다.
KEY_BLOCK_SIZE 를 지정한다고 해서 정확히 그 사이즈보다 작게 압축하는 것을 보장하기는 어렵다. 따라서 MySQL 은 내부적으로 한 번 테이블 페이지를 압축해보고, KEY_BLOCK_SIZE보다 큰 사이즈라면 페이지를 스플릿하여 다시 압축을 적용한 뒤 KEY_BLOCK_SIZE보다 큰지 비교해보고... 하는 방식으로 작아질때까지 스플릿과 압축 과정을 거쳐 KEY_BLOCK_SIZE 작은 사이즈로 디스크에 저장한다. 이런 방식으로 인해 KEY_BLOCK_SIZE를 너무 작게 설정해주면 테이블 압축에 시간이 오래 걸릴 수 있다.
KEY_BLOCK_SIZE 결정
KEY_BLOCK_SIZE는 직접 테스트를 통해 결정하는 것이 좋다. 임의의 테이블을 생성하고 KEY_BLOCK_SIZE 를 2, 4, 8 값을 주어가며 information_schema.INNODB_CMP_PER_INDEX 테이블을 조회하여 압축 횟수, 압축 실패율 등을 확인할 수 있다.
일반적으로 압축 실패율을 3~5%로 가져가는 것이 좋지만, 데이터 변경이 적고 INSERT만 일어나는 경우 성능이 조금 낮아지더라도 디스크 공간을 절약하는 것이 좋을 수 있다. 상황에 맞게 선택해야 한다.
압축된 페이지의 버퍼 풀 적재 및 사용
페이지가 압축된 상태라면 데이터를 읽어오거나 변경할 수 없다. 따라서 InnoDB 버퍼 풀에서는 기본 LRU 리스트에 더해 압축된 페이지들을 압축 해제해서 저장해놓는 Unzip_LRU 리스트를 별도로 관리한다.
압축이 적용된 페이지는 압축 페이지는 LRU 리스트에, 압축을 해제한 페이지는 Unzip_LRU 리스트에 두고 이중으로 메모리를 사용하여 동작하기 때문에 버퍼 풀 공간을 많이 사용하는 단점이 있다.
Unzip_LRU 리스트를 별도로 사용하는 이유는 매번 압축을 해제하고 압축하는 작업을 데이터 요청마다 수행할 경우 CPU 연산량이 너무 많아지기 때문이다. 따라서 Unzip_LRU 리스트를 통해 요청 패턴에 따라 자주 사용되는 경우에는 Unzip_LRU에 보관하고, 버퍼 풀 공간이 부족할 경우 Unzip_LRU 페이지만 제거하고 LRU의 압축 페이지는 남겨 놓는 등 내부적인 최적화 작업을 수행한다.
요청 패턴을 분석해서 최적화하는 것 외에도 CPU 사용량이 높으면 압축, 압축 해제를 피하기 위해 Unzip_LRU 리스트를 오래 유지한다거나, 디스크 I/O가 높은 서버에서는 버퍼 풀을 더 많이 사용하기 위해 Unzip_LRU 리스트의 비율을 낮춘다거나 등의 컴퓨팅 리소스 기반의 최적화도 수행한다.