이론 정리/Database

Real MySQL 6장 정리

철매존 2023. 12. 7. 00:14
728x90

# 데이터 압축

- 디스크에 저장된 데이터 파일 크기는 일반적으로 쿼리 성능, 백업, 복구 시간과 밀접하게 연결된다.
    - 쿼리 처리할 때에 데이터 페이지를 InnoDB 버퍼 풀로 읽어서
    - 새로운 페이지가 버퍼 풀로 적재되니까 더티 페이지가 더 자주 디스크로 기록되어서
    - 데이터 파일이 크면 백업/복구에 오래 걸린다

이를 해결하기 위해 도입된게 데이터 압축

## 페이지 압축

- Transparent Page Compression이라고도 한다.
    - MySQL서버가 디스크에 저장하는 시점에 데이터 페이지가 압축되어 저장되고, 읽어올 때에는 압축이 해제되니까
    - 즉 버퍼 풀에 데이터 페이지가 한 번 적재되면 InnoDB 스토리지 엔진은 압축이 해제된 상태로만 데이터 페이지를 관리함
    - 압축 여부와 관계없이 투명하다.
- 동작 방식
    - 16kb짜리를 압축하니까 7kb가 됐다고 가정하면
    - MySQL서버가 디스크에 7kb 기록(하면서 여기에 9kb 빈 데이터도 같이 기록해줌)
    - 그러고 디스크에 데이터 기록한 다음에 나머지 9kb는 빈 영역으로 유지(펀치홀)
    - 그래서 파일 시스템에는 7kb만 있고 9kb는 운영체제로 반납
- 문제
    - 위의 방식에서 보면 하드웨어 자체에서 기능을 지원해야 하는데, 시스템 관련 유틸리티가 펀치홀을 지원하지를 못한다.
    - 그래서 실제 페이지 압축은 많이 사용되지 않는다.

## 테이블 압축

이거는 위의 페이지 압축과 다르게 운영체제나 하드웨어에 대한 제약 없이 사용가능 -> 활용도가 높다.
이것도 이득은 있는데

- 버퍼 풀 공간 활용률이 낮음
- 쿼리 처리 성능이 낮음
- 빈번한 데이터 변경 시 압축률 떨어짐

요런 단점이 있다.
보면서 확인하면

### 압축 테이블 생성

- 일단 테이블 압축 전제 조건 -> 압축을 사용하려는 테이블이 별도의 테이블 스페이스를 사용해야 함
- 압축된 페이지의 타깃 크기(목표 크기)를 명시하는데, 2n(n은 2이상)으로만 가능. 그리고 페이지 크기가 32, 64kb인 경우는 테이블 압축 불가능
- 만약에 그래서 16kb에 대해 8kb로 목표가 설정되면
    - 먼저 16kb데이터 압축 진행
        - 그 결과가 8kb이하라면 그대로 디스크에 저장
        - 8kb를 넘어가면 스플릿해서 2개의 페이지에 8kb씩 저장
    - 나뉜 페이지 각각에 대해 압축 과정 반복 실행
- 위의 방향으로 압축한다. 
- 그래서 가장 중요한 것은 결국 목표 크기보다 작거나 같을 때 까지 계속 페이지를 스플릿하는거다.
    - 그래서 목표 크기가 잘못 설정되면 서버의 성능이 급격히 낮아진다.

### 목표 크기(KEY_BLOCK_SIZE) 결정

- 그래서 이걸 어떻게 결정할까?
- 샘플 데이터를 통해 4kb / 8kb로 테이블을 생성해서 저장해보고 판단하는게 좋다.
    - 샘플은 많으면 많을수록 좋은데 데이터 페이지가 최소 10개 정도는 생성되도록 insert해보는게 좋다.
- 이거 압축 실패률을 보면 된다.
    - 압축 실패 횟수(목표 용량을 초과해서 재압축 진행) / 전체 압축 횟수
        - 요게 3~5% 미만으로 하는게 좋다고 한다.
        - 물론 이게 꼭 낮으면 낮을수록 좋다는 아니고 상황에 따라 다름
            - 예를 들어 INSERT만 진행되는 경우는 데이터 압축 실패가 많아도 어쨌든 파일 크기가 많이 줄어들게 될 것이다.

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

- InnoDB 스토리지 엔진에서 압축된 테이블의 데이터 페이지를 버퍼 풀에 적재하면 압축된 상태와 압축이 해제된 상태 2개 버전을 관리한다.
    - InnoDB 스토리지 엔진은 디스크에서 읽은 상태 그대로의 데이터 페이지 목록을 관리하는 LRU리스트와 압축된 페이지들의 압축 해제 버전인 Unzip_LRU 를 별도 관리

근데 MySQL서버에는 압축된/안된 테이블이 공존한다.
그래서

- LRU리스트
    - 압축이 적용되지 않은 테이블의 데이터 페이지
    - 압축이 적용된 테이블의 압축된 데이터 페이지

두 개를 다 갖는다.
근데 Unzip_LRU같은 칭구는 압축이 적용되지 않은 테이블의 데이터 페이지는 가지지 않으며 압축이 적용된 테이블에서 읽은 데이터 페이지만 관리한다.
-> 압축된 테이블에 대해서 이중으로 사용 -> 데이터 낭비!

또 다른 문제점은 압축된 페이지에서 데이터를 읽거나 변경하기 위해서는 압축을 해제해야 한다는것.
-> 압축/해제는 CPU를 상대적으로 많이 소모한다.

- 해결책
    - 그래서 Unzip_LRU리스트를 별도로 관리하고 있다가 서버 유입 요청 패턴에 따라 적절하게
        - InnoDB버퍼 풀 공간이 필요한 경우
            - LRU리스트 : 원본 데이터 페이지(압축된형태)를 유지
            - Unzip_LRU리스트 : 압축 해제된 버전은 제거
            - 이렇게 해서 버퍼 풀 공간 확보
        - 압축된 데이터 페이지가 자주 사용되는 경우
            - Unzip_LRU리스트 : 압축 해제된 페이지를 계속 유지하면서 압축 및 압축 해제 작업 최소화.
        - 압축된 데이터 페이지가 사용되지 않아 LRU리스트에서 제거되는 경우
            - Unzip_LRU리스트에서도 제거

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

- CPU사용량이 높은 서버
    - 가능하면 압축 / 압축 해제를 피하기 위해 Unzip_LRU비율을 높여서 유지
- Disk IO 사용량이 높은 서버
    가능하면 Unzip_LRU리스트의 비율을 낮춰서 InnoDB 버퍼 풀의 공간을 더 확보하도록 작동