본문 바로가기
데이터베이스/Real MySQL

[Real MySQL 8.0] 6장 - 데이터 압축(페이지 압축과 테이블 압축)

by 책 읽는 개발자_테드 2022. 1. 4.
반응형

 

목차

· 디스크 데이터 파일 크기의 문제점

· 페이지 압축

· 테이블 압축


 

디스크 데이터 파일 크기의 문제점


MySQL 서버에서 디스크에 저장된 데이터 파일의 크기는 1. 쿼리의 처리 성능 2. 백업 및 복구 시간 3. 저장 비용과 밀접하게 연결된다.

 

- 디스크의 데이터 파일이 크면, 쿼리를 처리하기 위해 더 많은 데이터 페이지를 InnoDB 버퍼 풀로 읽어야 할 수 있고, 새로운 페이지가 버퍼 풀로 적재되므로 더티 페이지가 더 자주 디스크로 기록된다.

 

- 디스크의 데이터 파일이 클수록 백업 및 복구 시간이 오래 걸린다.

 

- 디스크의 데이터 파일이 클수록 저장 공간이 많이 필요하므로 비용 문제가 발생한다.

 

MySQL은 이러한 문제를 해결하기 위해 테이블 압축, 페이지 압축 두 가지의 데이터 압축 방법을 제공한다.

 

 

페이지 압축


· MySQL 서버가 디스크에 저장하는 시점에 데이터 페이지가 압축되어 저장되고, 디스크에서 데이터 페이지를 읽어올 때 압축이 해제되는 방식이다.

- 즉, 버퍼 풀에 데이터 페이지가 한 번 적재되면, InnoDB 스토리지 엔진은 압추기 해제된 상태로만 데이터 페이지를 관리한다.

- MySQL 서버의 내부 코드에서는 압축 여부과 관계없이 "투명(Transparent)"하게 작동하므로,

Transparent Page Compression이라고도 불린다.

 

· 사용 방법: 테이블을 생성하거나 변경할 때 COMPRESSION 옵션을 설정한다.

-- // 테입블 생성
mysql > CREATE TABLE t1 (c1 INT) COMPRESSION="zlib";

-- // 테이블 변경
mysql > ALTER TABLE t1 COMPRESSION="zlib";
mysql > OPTIMIZA TABLE t1;

 

펀치 홀(Punch hole)

· 16KB 데이터 페이지를 압축한 결과의 용량이 얼마나 될지 예측이 불가능한데 적어도 하나의 테이블은 동일한 크기의 페이지(블록)로 통일돼야 한다는 문제가 있다. 따라서 페이지 압축 기능은 운영체제별로 특정 버전의 파일 시스템에서만 지원되는 펀치 홀이라는 기능을 사용한다.

 

TODO: 왜 하나의 테이블은 동일한 크기의 페이지로 통일 돼어야 하는가?

 

· 페이지 압축 작동 방식 - 운영체제(파일 시스템)의 블록 사이즈가 512바이트인 경우

1. 16KB 페이지를 압축(압축 결과를 7KB로 가정)

2. MySQl 서버는 디스크에 압축된 결과 7KB를 기록 (이때 MySQL 서버는 압축 데이터 7KB에 9KB의 빈 데이터를 기록)

3. 디스크에 데이터를 기록한 후, 7KB 이후의 공간 9KB에 대해 펀치 홀 생성

4. 파일 시스템은 7KB만 남기고 나머지 디스크의 9KB 공간은 다시 운영체제로 반납

- 위 방식으로 MySQL 서버는 특정 테이블에 대해 16KB 크기의 페이지를 유지하면서도 압축된 다양한 크기의 데이터 페이지를 디스크에 저장하고, 압축된 만큼의 공간을 절약할 수 있다.

 

 

MySQL 서버 페이지 압축의 문제

· 문제 1 - 펀치 홀 기능은 운영체제뿐만 아니라 하드웨어 자체에서도 해당 기능을 지원해야 사용 가능하다.

· 문제 2 - 아직 파일 시스템 관련 명령어(유틸리티)가 펀치 홀을 지원하지 못한다.

- MySQL 서버는 백업 및 복구 과정에서 데이터 파일 복사 과정이 실행되고, 이외에도 많은 파일 관련 유틸리티들을 사용한다. 이때, 펀치 홀이 적용되어 실제 데이터 파일의 크기가 1GB라고 하더라도 "cp" 같은 파일 복사 명령 또는 XtraBackup 같은 툴이 파일을 복사하면 펀치 홀이 다시 채워져서 데이터 파일의 크기는 원본 크기인 10GB가 될 수도 있다.

 

· 위와 같은 이유로 실제 페이지 압축은 많이 사용되지 않는다.

 

 

테이블 압축


· 운영체제나 하드웨어에 대한 제약 없이 사용할 수 있으므로, 페이지 압축보다 일반적으로 활용도가 높다.

· 장점: 디스크의 데이터 파일 크기를 줄일 수 있다.

· 단점: 1. 버퍼 풀 공간 활용률이 낮음

          2. 쿼리 처리 성능이 낮음

          3. 빈번한 데이터 변경 시 압축률이 떨어짐

 

압축 테이블 생성

· 테이블 압축을 사용하기 위한 전제 조건: 압축을 사용하려는 테이블이 별도의 테이블 스페이스를 사용해야 한다.

- innodb_file_per_table 시스템 변수가 ON으로 설정된 상태에서 테이블이 생성돼야 한다.

- 테이블 압축을 사용하는 테이블은 ROW=COMPRESSED 옵션을 명시한다.

- KEY_BLOCK_SIZE 옵션을 이용해 압축된 페이지의 목표 크기를 명시한다. 2 이상의 수 2n으로만 설정할 수 있다.

  옵션값은 KB 단위를 설정한다.

- 페이지 크기가 32KB 또는 64KB인 경우에는 테이블 압축을 적용할 수 없다.

 

mysql > SET GLOBAL innodb_file_per_table=ON;

-- // ROW_FORMAT 옵션과 KEY_BLOCK_SIZE 옵션을 모두 명시
mysql > CREATE TABLE compressed_table (
   c1 INT PRIMARY KEY
)
ROW_FORMAT=COMPRESSED
KEY_BLOCK_SIZE=8;

-- // ROW_FORMAT 옵션만 명시
mysql > CREATE TABLE compressed_table (
   c1 INT PRIMARY KEY
)
KEY_BLOCK_SIZE=8;

 

- 두 번째 테이블 생성 구문처럼 ROW_FORMAT 옵션이 생략되면, 자동으로 ROW_FORMAT=COMPRESSED 옵션이 추가되어 생성된다.

 

· InnoDB 스토리지 엔진이 압축을 적용하는 방법 - 목표 크기 8KB로 가정:

1. 16KB의 데이터 페이지를 압축

- 압축된 결과가 8KB 이하이면 그대로 디스크에 저장(압축 완료)

- 압축된 결과가 8KB를 초과하면 원본 페이지를 스플릿해서 2개의 페이지에 8KB씩 저장

2. 나뉜 페이지 각각에 대해 "1"번 단계를 반복 실행

- 테이블 압축에서는 InnoDB 스토리지 엔진의 "InnoDB I/O" 레이어는 아무런 역할을 하지 않는다.

- 주의사항: 목표 크기 보다 작거나 같을 때까지 반복해서 페이지를 스필릿하므로, 목표 크기가 잘못되면 MySQL의 처리 성능이 급격히 떨어질 수 있다.

 

KEY_BLOCK_SIZE 결정

· 테이블 압축에서 가장 중요한 부분은 압축된 결과가 어느 정도 될지 예측해서 KEY_BLOCK_SIZE를 결정하는 것이다.

· 테이블 압축을 적용하기전 KEY_BLOCK_SIZE를 다르게 설정하여 테이블을 생성하고, 샘플 제이터를 저장해 적절한지 판단하자.

- KEY_BLOCK_SIZE는 4KB 또는 8KB로 설정하고, 최소한 데이터 페이지가 10개 정도 생성되도록 테스트 데이터를 INSERT해보자.

· 자세한테스트 방법: Real MySQL 8.0 1권 p190

 

· 일반적으로 압축 실패율이 3~5% 미만을 유지하도록 KEY_BLOCK_SIZE를 선택하는 거이 좋다.

· 압축 데이터 파일의 용량이 비슷한 경우(압축 효율), 압축 파일 실패율이 낮은 KEY_BLOCK_SIZE를 선택한다.

· INSERT만 되고 변경과 조희가 거의 없는 테이블(예:로그)의 경우 압축을 하는 것이 효율적이고,

데이터가 빈번히 조회 및 변경되는 테이블은 압축을 안하는 것이 좋다.

· 테이블 압축은 zlib을 이용해 압축을 실행하고, 압축 알고리즘은 많은 CPU 자워능ㄹ 소모한다.

 

압축된 페이지의 버퍼 풀 적재 및 사용

·  InnoDB 스토리지 엔진은 압축된 테이블의 데이터 페이지 버퍼 풀에 적재하면, 두 가지 상태의 데이터 페이지를 관리한다.

1. 디스크에서 읽은 상태 그대로의 데이터 페이지 목록(압축 상태)을 관리하는 LRU 리스트

2. 압축 해제 버전인 Unzip_LRU 리스트

- Unzip_LRU 리스트는 압축이 적용되지 않은 테이블의 데이터 페이지는 가지지 않는다.

 

· 따라서 LRU 리스트는 압축된 페이지와 압축되지 않은 페이지를 모두 가질 수 있다.

 

· 문제점: 

1. 압축된 테이블에 대해 버퍼 풀 공간을 이중으로 사용함으로써 메모리를 낭비하는 효과를 갖는다.

2. 압축된 페이지에서 데이터를 읽거나 변경하기 위해서는 압축을 해제해야 하는데, 이는 CPU를 많이 소모하는 작업이다.

 

· 해결: MySQL 서버로 유입되는 요청 패턴에 따라서 적절히(Adaptive) Unzip_LRU 리스트의 데이터를 관리(유지 또는 삭제)한다.

1. 버퍼 풀 공간이 필요하면, Unzip_LRU 리스트의 데이터(압축해제)를 제거해 공간을 확보

2. 압축된 데이터 페이지가 자주 사용되면, Unzip_LRU 리스트에 압축 해제된 페이지를 계속 유지 -> 압축 및 압축 해제 작업 최소화

3. 압축된 데이터 페이지가 사용되지 않아 LRU 리스트에서 제거되면, Unzip_LRU 리스트에서도 함께 제거

 

· InnoDB 스토리지 엔진의 버퍼 풀에서 압축 해제된 버전의 데이터 페이지를 적절한 수준으로 유지하기 위한 어댑티브 알고리즘:

1. CPU 사용량이 높은 서버에서는 가능하면 압축 해제를 피하기 위해 Unzip_LRU의 비율을 높여 유지

2. Disk IO 사용량이 높은 서버에서는 가능하면 Unzip_LRU 리스트의 비율을 낮춰서 InnoDB 버퍼 풀의 공간을 더 확보

 

테이블 압축 관련 설정

· 데이블 압축과 연관된 시스템 변수로, 페이지 압축 실패율을 낮추기 위한 튜닝 포인트를 제공한다.

innodb_cmp_per_index_enabled 테이블 압축이 사용된 테이블의 모든 인덱스별로 압축 성공 및 압축 실행 횟수 수집
innodb_compression_level InnoDB 테이블 압축은 zlib 압축 알고리즘만 지원하며, 해당 시스템 변수를 이용해 압축률을 설정한다.

0~9의 범위를 갖고, 값이 작을수록 압축 속도는 빠르지만 저장 공간은 커진다. 기본값은 6이다. 

압축 속도는 CPU 자원 소모량과 동일한 의미다. 

innodb_compression_failure_threshold_pct 테이블 단위로 압축 실패율이 해당 값 보다 커지면 압축을 실행하기 전 원본 데이터 페이지 끝에 의도적으로 일정 크기의 빈공간을 추가된다.

빈 공간은 압축률을 높여 압축 결과가 KEY_BLOCK_SIZE보다 작어지게 만든다.
추가하는 빈 공간을 패딩이라고 한다.
inno_compression_pad_pct_max 패딩은 압축 실패율이 높아질수록 계족 증가하지만 해당 값 이상을 넘을 수 없다.
설정값에는 % 값을 설정하고, 전체 데이터 페이지 크기 대비 패딩 공간의 비율을 의미한다.

 

· 세부사항: Real MySQl 8.0 1권 p193

 

출처

 Real MySQl 8.0 1권

반응형

댓글