해당 포스트는
MySQL
를 학습하며 필요한 내용을 정리한 포스트입니다.
🌈 6. 데이터 압축
MySQL 서버에서 디스크에 저장된 데이터 파일의 크기는 쿼리의 처리 성능과 백업 및 복구 시간과도 밀접하게 연결된다.
디스크의 데이터 파일이 크면 클수록
쿼리를 처리하기 위해서 더 많은 데이터 페이지를 InnoDB 버퍼 풀로 읽어야 할 수도 있고,
새로운 페이지가 버퍼 풀로 적재되기 때문에 그만큼 더티 페이지가 더 자주 디스크로 기록돼야 한다.
데이터 파일이 크면 클수록 백업 시간이 오래 걸리며, 복구하는 데도 그만큼의 시간이 걸린다.
때문에 많은 DBMS에서 이런 문제를 해결하기 위해 데이터 압축 기능을 제공한다.
MySQL 서버에서 사용 가능한 압축 방식은 크게 테이블 압축
과 페이지 압축
의 두 가지 종류로 구분
두 방식은 매우 다르게 작동한다.
💻 6.1 페이지 압축
페이지 압축은 “Transparent Page Compression
“이라고도 불린다.
MySQL 서버가 디스크에 저장하는 시점에 데이터 페이지가 압축되어 저장되고, 반대로 MySQL 서버가 디스크에서 데이터 페이지를 읽어올 때 해제되기 때문이다.
즉, 버퍼 풀에 데이터 페이지가 한 번 적재되면 InnoDB 스토리지 엔진은 압축이 해제된 상태로만 데이터 페이지를 관리한다.
여기서 한 가지 문제점이 있는데, 16KB 데이터 페이지를 압축한 결과가 용량이 얼마나 될지 예측이 불가능한데 적어도 하나의 테이블은 동일한 크기의 페이지(블록)로 통일돼야 한다는 것이다.
그래서 페이지 압축 기능은 운영체제별로 특정 버전의 파일 시스템에서만 지원되는 펀치 홀(Punch hole)이라는 기능을 사용한다.
MySQL 서버는 특정 테이블에 대해 16KB 크기의 페이지를 유지하면서도 압축된 다양한 크기의 데이터 페이지를 디스크에 저장하고 압축된 만큼의 공간을 절약할 수 있다.
1
2
3
4
1. 16KB 페이지를 압축 (압축 결과를 7KB로 가정)
2. MySQL 서버는 디스크에 압축된 결과 7KB를 기록 (이때 MySQL 서버는 압축 데이터 7KB에 9KB의 빈 데이터를 기록)
3. 디스크에 데이터를 기록한 후, 7KB 이후의 공간 9KB에 대해 펀치 홀(Punch-hole)을 생성
4. 파일 시스템은 7KB만 남기고 나머지 디스크의 9KB 공간은 다시 운영체제로 반납
MySQL 페이지 압축은 펀치 홀 기능이 운영체제뿐만 아니라 하드웨어 자체에서도 해당 기능을 지원해야 사용 가능하다.
아직 파일 시스템 관련 명령어(유틸리티)가 펀치 홀을 지원하지 못한다는 점으로 인해 많이 사용되지 않는 상태다.
만약 페이지 압축을 이용하다면 테이블을 생성하거나 변경할 때 아래와 같이 COMPRESSION
옵션을 설정하면 된다.
1
2
3
4
5
6
-- // 테이블 생성 시
mysql> CREATE TABLE t1 (c1 INT) COMPRESSION="zlib";
-- // 테이블 변경 시
mysql> ALTER TABLE t1 COMPRESSION="zlib";
mysql> OPTIMIZE TABLE t1;
💻 6.2 테이블 압축
운영체제나 하드웨어에 대한 제약 없이 사용할 수 있기 때문에 더 활용도가 높다.
디스크의 파일 크기를 줄일 수 있기 때문에 그만큼의 이득은 있지만, 몇 가지 단점이 있다.
퍼버 풀 공간 활용률이 낮다.
쿼리 처리 성능이 낮다.
빈번한 데이터 변경 시 압축률이 떨어진다.
🍳 압축 테이블 생성
테이블 압축을 사용하기 위한 전제 조건으로 압축을 사용하려는 테이블이 별도의 테이블 스페이스를 사용해야 한다.
innodb_file_per_table
시스템 변수가 ON
으로 설정된 상태에서 테이블이 생성돼야 한다.
테이블을 생성할 때 ROW_FORMAT=COMPRESSION
옵션을 명시해야 한다.
KEY_BLOCK_SIZE
옵션을 이용해 압축된 페이지의 타깃 크기(목표 크기)를 명시하는데, 2n(n값은 2 이상)으로만 설정할 수 있다.
InnoDB 스토리지 엔진의 페이지 크기(innodb_page_size)가 16KB라면 KEY_BLOCK_SIZE는 4KB 또는 8KB로만 설정할 수 있다.
페이지 크기가 32KB 또는 64KB인 경우에는 테이블 압축을 적용할 수 없다.
테이블 압축 방식에서 가장 중요한 것은 원본 데이터 페이지의 압축 결과가 목표 크기(KEY_BLOCK_SIZE)보다 작거나 같을 때까지 반복해서 페이지를 스플릿하는 것이다.
목표 크기가 잘못 설정되면 MySQL 서버의 처리 성능이 급격히 떨어질 수 있으니 주의하자.
🍳 KEY_BLOCK_SIZE 설정
테이블 압축에서 가장 중요한 부분은 압축된 결과가 어느 정도가 될지를 예측해서 KEY_BLOCK_SIZE를 결정하는 것이다.
테이블 압축을 적용하기 전에 먼저 KEY_BLOCK_SIZE를 4KB 또는 8KB로 테이블을 생성해서 샘플 데이터를 저장해보고 적절한지 판단하는 것이 좋다.
이때 샘플 데이터는 많으면 많을수록 더 정확한 테스트가 가능하므로, 최소한 테이블의 데이터 페이지가 10개 정도는 생성되도록 테스트 데이터를 INSERT 해보는 것이 좋다.
🍳 압축된 페이지의 버퍼 풀 적재 및 사용
InnoDB 스토리지 엔진은 압축된 테이블의 데이터 페이지를 버퍼 풀에 적재하면 압축된 상태와 압축이 해제된 상태 2개 버전을 관리한다.
InnoDB 스토리지 엔진은 디스크에서 읽은 상태 그대로의 데이터 페이지 목록을 관리하는 LRU 리스트와 압축된 페이지들의 압축 해제 버전인 Unzip_LRU
리스트를 별도로 관리하게 된다.
MySQL 서버에는 압축된 테이블과 압축되지 않은 테이블이 공존하므로 결국 LRU 리스트는 아래와 같이 압축된 페이지와 압축되지 않은 페이지를 모두 가질 수 있다.
압축이 적용되지 않은 테이블의 데이터 페이지
압축이 적용된 테이블의 압축된 데이터 페이지
Unzip_LRU 리스트는 압축이 적용되지 않은 테이블의 데이터 페이지는 가지지 않으며, 압축이 적용된 테이블에서 읽은 데이터 페이지만 관리한다.
물론 Unzip_LRU 리스트에는 압축을 해제한 상태의 데이터 페이지 목록이 관리된다.
📚 레퍼런스
백은빈, and 이성욱. Real MySQL 8.0 : 개발자와 DBA를 위한 MySQL 실전 가이드 1 / 백은빈, 이성욱 지음. (2021). Web.
백은빈, and 이성욱. Real MySQL 8.0 : 개발자와 DBA를 위한 MySQL 실전 가이드. 2 / 백은빈, 이성욱 지음 (2021). Web.