-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
180 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
# 6. 데이터 압축 | ||
|
||
### 목차 | ||
|
||
- [6.1 페이지 압축](#61-페이지-압축transparent-page-compression) | ||
- [6.2 테이블 압축](#62-테이블-압축) | ||
|
||
<br> | ||
|
||
> MySQL 서버에서 디스크에 저장된 데이터 파일의 크기는 일반적으로 **쿼리의 처리 성능**과도 직결되지만 **백업 및 복구 시간**과도 밀접하게 연결된다. | ||
> | ||
> 디스크의 데이터 파일의 크기가 크면? | ||
> - 쿼리를 처리하기 위해 더 많은 페이지를 InnoDB 버퍼 풀에서 읽어야 할 수 있다. | ||
> - 새로운 페이지가 버퍼 풀로 적재되기 때문에 그만큼 더티 페이지가 더 자주 디스크로 기록되어야 한다. | ||
> - 백업 믹 복구 시간이 오래 걸린다. 또한, 그만큼 저장 공간이 필요하기 때문에 비용 문제도 발생한다. | ||
> | ||
> 많은 DBMS가 이런 문제점을 해결하기 위해 데이터 압축 기능을 제공한다. | ||
> - MySQL 서버에서는 데이터 압축 방식은 크게 `테이블 압축`과 `페이지 압축`으로 나뉘어진다. | ||
<br> | ||
|
||
## 6.1 페이지 압축(Transparent Page Compression) | ||
|
||
### 압축 방식 | ||
|
||
- 디스크에 저장하는 시점에 데이터 페이지가 압축되어 저장되고, 디스크에서 읽어올 때 압축 해제된다. | ||
- 즉, 버퍼 풀에 데이터 페이지가 한 번 적재되면 InnoDB 스토리지 엔진은 압축이 해제된 상태로만 데이터 페이지를 관리한다. | ||
- 그래서 MySQL 서버의 내부 코드에서는 압축 여부와 관계없이 `투명(Tranparen)` 하게 작동한다. | ||
- 문제점 | ||
- 데이터 페이지를 압축한 결과가 용량이 얼마나 될지 예측이 불가능하다. | ||
- 적어도 하나의 테이블은 동일한 크기의 페이지(블록) 로 통일돼야 한다. | ||
- 그래서 페이지 압축 기능은 `펀치 홀` 기능을 사용한다. | ||
|
||
<br> | ||
|
||
### 펀치홀(Punch-hole) | ||
|
||
<img width="450" src="https://github.com/user-attachments/assets/ee83a657-8e81-44f5-8899-791b576c2c0b" /> | ||
|
||
``` | ||
1. 16KB 페이지를 압축 (압축 결과를 7KB로 가정) | ||
2. MySQL 서버는 디스크에 압축된 결과 7KB를 기록 (이때 MySQL 서버는 압축 데이터 7KB에 9KB의 빈 데이터를 기록) | ||
3. 디스크에 데이터를 기록한 후, 7KB 이후의 공간 9KB에 대해 펀치 홀을 생성 | ||
4. 파일 시스템은 7KB만 남기고 나머지 디스크의 9KB 공간은 다시 운영체제로 반납 | ||
``` | ||
- 실제 디스크 공간의 7KB만 차지하지만, 운영체제에서 읽으면 압축된 데이터 7KB와 펀치 홀 공간인 9KB를 합쳐서 16KB를 읽는다. | ||
|
||
|
||
- 문제점 | ||
- 운영체제뿐만 아니라 하드웨어 자체에서도 해당 기능을 지원해야 사용 가능하다는 점 | ||
- 아직 파일 시스템 관련 명령어가 펀치홀을 지원하지 못한다. | ||
- 복사 및 복제하는 과정에서 펀치 홀이 다시 채워져서 데이터 파일의 크기가 원본 크기가 될 수 있다. | ||
- 이러한 이유로 실제 페이지 압축을 많이 사영되지 않는 상태이다. | ||
|
||
|
||
<br> | ||
<br> | ||
|
||
## 6.2 테이블 압축 | ||
|
||
- 테이블 압축은 페이지 압축과 달리 운영체제나 하드웨어의 제약 없이 사용할 수 있기 때문에 활용도가 더 높다. | ||
- 디스크의 데이터 파일 크기를 줄일 수 있라는 이득이 있다. | ||
- 하지만 몇 가지 단점도 있다. | ||
- 버퍼 풀 공간 활용률이 낮음 | ||
- 쿼리 처리 성능이 낮음 | ||
- 빈번한 데이터 변경 시 압축률이 떨어짐 | ||
|
||
<br> | ||
|
||
### 6.2.1 압축 테이블 생성 | ||
|
||
#### 전체 조건 | ||
|
||
```sql | ||
CREATE TABLE COMPRESSED_TABLE( | ||
C1 INT PRIMARY KEY, | ||
) | ||
ROW_FORMAT=COMPRESSED | ||
KEY_BLOCK_SIZE=8; | ||
``` | ||
|
||
- 테이블 압축을 사용하려면 압축을 사용하려는 테이블이 별도의 테이블 스페이스를 사용해야 한다. (`innodb_file_per_table` 시스템 변수 ON 상태로 생성) | ||
- 그리고 압축 테이블을 생성할 때 `ROW_FORMAT=COMPRESSED` 옵셥을 설정하고, `KEY_BLOCK_SIZE` 옵션을 이용해 압축된 페이지의 타깃 크기를 명시한다. | ||
- `KEY_BLOCK_SIZE` 옵션은 압축된 페이지가 저장될 페이지의 크기를 지정한다. | ||
- `KEY_BLOCK_SIZE`는 2n(n >= 2)으로만 설정할 수 있다. | ||
- InnoDB 스토리지 엔진의 페이지 크기(`innodb_page_size`)가 16KB 라면 4KB 또는 8KB로만 설정할 수 있다. | ||
|
||
<br> | ||
|
||
#### 압축 방식 | ||
|
||
<img width="300" src="https://github.com/user-attachments/assets/dea35d6b-dc40-4cae-8b48-2c31e558d368" /> | ||
|
||
``` | ||
1. 16KB 의 데이터 페이지를 압축 | ||
1.1 압축된 결과가 8KB 이하이면 그대로 디스크에 저장 ( 압축 완료 ) | ||
1.2 압축된 결과가 8KB 를 초과하면 원본 페이지를 스플릿 (split)해서 2 개의 페이지에 8KB 씩 저장 | ||
2. 나뉜 페이지 각각에 대해 1" 번 단계를 반복 실행 | ||
``` | ||
|
||
- 원본 데이터 페이지의 압축 결과가 목표 크기(`KEY_BLOCK_SIZE`)보다 작거나 같을 때까지 반복해서 페이지를 스플릿한다. | ||
- 그래서 목표 크기가 잘못 설정되면 MySQL 서버의 처리 성능이 급격히 떨어질 수 있으니 주의해야 한다. | ||
|
||
<br> | ||
|
||
### 6.2.2 KEY_BLOCK_SIZE 결정 | ||
|
||
> 테이블 압축에서 가장 중요한 부분이 압축된 결과가 어느 정도가 될지 예측해서 KEY_BLOCK_SIZE를 결정하는 것이다. | ||
> 그래서 테이블을 압축하기 전에 KIB 또는 8KIB 로 테이블을 생성해서 샘플 데이터를 저장해보고 적절한지 판단하는 것이 좋다. | ||
```sql | ||
mysql> USE employees; | ||
|
||
-- // 테이블 압축을 사용하는 예제 테이블을 생성 | ||
mysql> CREATE TABLE employees_comp4k ( | ||
emp_no int NOT NULL, | ||
birth_date date NOT NULL, | ||
first_name varchar (14) NOT NULL, | ||
last_name varchar (16) NOT NULL, | ||
gender enum( 'M', 'F') NOT NULL, | ||
hire_date date NOT NULL, | ||
PRIMARY KEY (emp_no), | ||
KEY ix_firstname (first_name), | ||
KEY ix_hiredate (hire_date) | ||
) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; | ||
|
||
-- // 테스트를 실행하기 전에 innodb_cmp_per_index_enabled 시스템 변수를 ON 으로 변경해야 인덱스별로 압축 실행 횟수와 성공 횟수가 기록된다. | ||
mysql> SET GLOBAL innodb_mp_per_index_enabled=ON; | ||
|
||
-- // employees 테이블의 데이터를 그대로 압축 테스트 테이블로 저장 | ||
mysql> INSERT INTO employees_comp4k SELECT * FROM employees; | ||
|
||
-- // 인덱스별로 압축 횟수와 성공 횟수, 압축 실패율 조회 | ||
mysql > SELECT | ||
table_name, index_name, compress_ops, compress_ops_ok, | ||
(compress_ops-compress_ops_ok)/compress_ops* 100 as compression_failure_pct | ||
FROM information_schema. INNODB_CMP_PER_INDEX; | ||
``` | ||
|
||
- 일반적으로 압축 실패율은 3~5% 미만으로 유지할 수 있게 `KEY_BLOCK_SIZE`를 선택하는 것이 좋다. | ||
- 압축 실패율이 높다고 해서 압축을 사용하지 말아야 하는 것은 아니다. | ||
- INSERT만 되는 로그 테이블의 경우, 한번 INSERT되면 이후에 변경되지 않기 때문에 재압축하더라도 파일의 크기가 큰 폭으로 줄어든다면 큰 손해는 아니다. | ||
- 반대로 압축 실패욜이 높지 않은 경우라고 하더라도 테이블의 데이터가 매우 빈번하게 조회되고 변경된다면 압축은 고려ㅏ지 않는 것이 좋다. | ||
- 압축 알고리즘은 많은 CPU 자원을 소모한다. | ||
|
||
<br> | ||
|
||
### 6.2.3 압축된 페이지의 버퍼 풀 적재 및 사용 | ||
|
||
- InnoDB는 압축된 테이블의 데이터 페이지를 버퍼 풀에 적재하면 압축된 상태와 압축이 해제된 상태 2개 버전을 관리한다. | ||
- 그래서 InnoDB 스토리지 엔진은 압축된 그대로의 데이터 페이지를 관리하는 `LRU 리스트`와 압축이 해제된 페이지를 관리하는 `Unzip_LRU 리스트`를 별도로 관리한다. | ||
- 문제점 | ||
- 압축된 테이블에 대해서는 버퍼 풀의 공간을 이중으로 사용함으로써 메모리를 낭비하는 효과가 있다. | ||
- 또한, 압축된 페이지에서 데이터를 읽거나 변경하기 위해 압축을 해제해야 하는데, 이러한 작업은 CPU를 상대적으로 많이 소모한다. | ||
- 이러한 두 가지 단점을 보완하기 위해 `Unzip_LRU 리스트`를 별도로 관리하고 있다가 MySQL 서버로 유입되는 요청 패턴에 따라서 적절히(`Adaptive`) 처리를 수행한다. | ||
- InnoDB 버퍼 풀 공간이 필요한 경우 | ||
- LRU 리스트에서 원본 데이터 페이지(압축된 형태)는 유지하고, Unzip_LRU 리스트에서 압축 해제된 버전은 제거해서 버퍼 풀 공간을 확보한다. | ||
- 압축된 데이터 페이지가 자주 사용되는 경우 | ||
- Unzip_LRU 리스트에 압축 해제된 페이지를 계속 유지하면서 압축 및 압축 해제 작업을 최소화한다. | ||
- 압축된 데이터 페이지가 사용되지 않아 LRU 리스트에서 제거되는 경우 | ||
- Unzip_LRU 리스트에서도 함께 제거한다. | ||
|
||
#### 어댑티브(적응적인) 알고리즘 | ||
- 버퍼 풀에서 압축 해제된 버전의 데이터 페이지를 적절한 수준으로 유지하는 방법 | ||
- CPU 사용량이 높은 서버 → 압축과 압축 해제를 피하기 위해 Unzip_LRU의 비율 높이기 | ||
- Disk IO 사용량이 높은 서버 → InnoDB 버퍼 풀의 공간을 더 확보하기 위해 Unzip_LRU의 비율 낮추기 | ||
|
||
<br> | ||
|
||
### 6.2.4 테이블 압축 관련 설정 | ||
|
||
> 테이블 압축을 사용할 때 연관된 시스템 변수가 몇 가지 있는데, 모두 페이지의 압축 실패율을 낮추기 위해 필요한 튜닝 포인트를 제공한다. | ||
- `innodb_cmp_per_index_enabled` | ||
- `innodb_compression_level` | ||
- `innodb_compression_failure_threshold_pct`, `innodb_compression_pad_pct_max` | ||
- `innodb_log_compressed_pages` | ||
|
||
<br> | ||
<br> |