2014년 7월 25일 금요일

TokuDB Fast Bulk Loader - INSERT INTO ... SELECT 문에 대한 이해

TokuDB 에서는 LOAD DATA FILE, CTAS, INSERT INTO ...SELECT문과 오프라인 인덱스 생성 작업시, 멀티 코어를 사용하여 병렬로 loader가 동작하는 Fast Bulk Loader 기능을 제공한다.
이 중에서 INSERT INTO ... SELECT문을 사용할 때 Fast Bulk Loader가 어떻게 움직이는지, 그리고 주의 사항에 대해서 소개하고자 한다.

Bulk Loader와 관련된 파라미터

tokudb_tmp_dir

이 파라미터에 지정된 디렉토리에 TokuDB bulk loader가 임시 파일을 저장한다. 이 파라미터에 지정된 디렉토리의 디스크 공간이 부족할 경우 bulk loader가 실패하고 에러가 발생한다.

tokudb_loader_memory_size

Bulk loader 가 사용하게 될 메모리를 제한하는 세션 변수이다. 기본값은 100M이며, 초 대형 테이블인 경우 이 값을 증가시켜 bluk loader의 성능을 향상 시킬 수 있다. Bulk loader에서 사용할 메모리는 tokudb_cache_size 파라미터에 지정된 TokuDB cache에서 할당받으므로 tokudb_cache_size 파라미터에 지정된 값보다 작아야 한다.

tokudb_read_buf_size

TokuDB의 읽기 버퍼 사이즈로써 큰 범위를 스캔하여 bulk fetch를 할 경우 이 값을 크게 조정하도록 한다. 기본값은 131,072(128KB) 이다.

tokudb_load_save_space

이 파라미터는 TokuDB bulk loader의 동작 방식을 결정하는 세션 변수이다. 만일 off로 지정되어 있을 경우 중간 생성 파일을 압축하지 않는다. 따라서 TokuDB bulk loader는 on 상태일 때보다 cpu를 보다 적게 사용한다. 하지만 보다 많은 디스크 공간을 사용하므로 주의해야 한다. 기본값은 on이다.

tokudb_prelock_empty

TokuDB에서 비어있는 테이블에 대해 첫 조작이 일어날 경우 전체 테이블에 대해 LOCK을 선점한다. 만일 비어있는 테이블에 대해 하나의 트랜잭션이 loading을 시작할 경우, loading을 빨리 끝내야겠구나라고 간주하고 TABLE LOCK을 걸고 loading job을 실행한다. 따라서 이후에 들어오는 같은 테이블에 대한 트랜잭션을 브로킹된다. 이를 preemptive prelocking 이라고 한다. tokudb_prelock_empty = off 로 설정하면 비어있는 테이블에 대해 TABLE LOCK을 선점하는 것을 막을 수 있다. 하지만 loading을 fast bulk loader로 동작하지 않는다. 기본값은 on이다.



TokuDB Fast Bulk Loader는 크게 Fetch와 Load 단계로 나누어진다.


Fetch 단계

tokudb_tmp_dir 파라미터에 지정된 디렉토리에 loding할 입력 데이터를 임시 저장한다. 이 단계는 tokudb_load_save_space 세션 변수에 의해 임시 데이터의 압축 여부를 결정한다.
임시 파일은 아래와 같이 fetch 단위로 각각 생성된다.

$ ls -al
-rw------- 1 mysql dba 11335514 7월 25 09:20 tokuld04pZJY
-rw------- 1 mysql dba 24249800 7월 25 07:43 tokuld08nQkb
-rw------- 1 mysql dba 21165661 7월 25 07:47 tokuld08sBgG
-rw------- 1 mysql dba 10838587 7월 25 09:37 tokuld0CKDyC
-rw------- 1 mysql dba 11055343 7월 25 09:36 tokuld0EkBvj
...

이 때 show processlist 명령어로 현재 bluk loader가 진행 중인 사항을 확인할 수 있는데, 아래와 같이 Fetched about xxxx rows, loading data still remains 라고 표시된다.
만일 Fetched about xxxx rows, INSERTS .... xxxx ROWS 라고 표시되면 INSERT INTO ... SELECT 문이 bulk loader로 동작하는 하는 것이 아니므로 주의하기 바란다.
또한 INSERT INTO ... SELECT 문으로 테이블에 첫 입력을 할 때 bulk loader로 동작하지만, 그 후에 실행하는 INSERT INTO ... SELECT 문은 bulk loader로 동작하지 않는다. 이 문제는 TokuDB 7.1.8 에서 bulk loader로 동작할 수 있도록 수정될 예정이라고 한다.

> show processlist
Queried about 2040287006 rows, Fetched about 2040287000 rows, loading data still remains
...
...

TokuDB에서 저장 파일 및 Fractal Tree Index의 물리적 위치는 information_schema.tokudb_file_map 에서 조회할 수 있다.

+------------------------------------------+------------------------------------------------------------+--------------+----------------+-----------------------+
| dictionary_name                          | internal_file_name                                         | table_schema | table_name     | table_dictionary_name |
+------------------------------------------+------------------------------------------------------------+--------------+----------------+-----------------------+
| ...t1#P#PF_201401-key-cl1_page_accesslog | /.../_db1_t1_P_PF_201401_key_cl1_t1_ad97db_1_19_B_0.tokudb | db1          | t1#P#PF_201401 | key-cl1_t1            |
| ...t1#P#PF_201401-key-ix1_page_accesslog | /.../_db1_t1_P_PF_201401_key_ix1_t1_ad97db_1_19_B_1.tokudb | db1          | t1#P#PF_201401 | key-ix1_t1            |
| ...t1#P#PF_201401-main                   | /.../_db1_t1_P_PF_201401_main_ad97db_1_19_B_2.tokudb       | db1          | t1#P#PF_201401 | main                  |
| ...t1#P#PF_201401-status                 | /.../_db1_t1_P_PF_201401_status_ad97c0_1_19.tokudb         | db1          | t1#P#PF_201401 | status                |
...
+------------------------------------------+------------------------------------------------------------+--------------+----------------+-----------------------+

tokudb_data_dir에서 지정된 데이터 디렉터리에서 ls 명령어로 조회하면 해당 파일을 확인할 수 있다.

-rwxrwx--x 1 mysql mysql 32K 7 25 06:31 _db1_t1_P_PF_201401_key_cl1_t1_ad97c0_3_19.tokudb
-rwxrwx--x 1 mysql mysql 32K 7 25 06:31 _db1_t1_P_PF_201401_key_ix1_t1_ad97c0_4_19.tokudb
-rwxrwx--x 1 mysql mysql 32K 7 25 06:31 _db1_t1_P_PF_201401_main_ad97c0_2_19.tokudb
-rwxrwx--x 1 mysql mysql 64K 7 25 07:12 _db1_t1_P_PF_201401_status_ad97c0_1_19.tokudb

load 단계

임시 파일을 테이블 및 인덱스에 적재하는 단계이다. 이 때 멀티 코어를 사용하여 병렬로 loder를 동작시킨다. 이 사실은 top 명령어로 쉽게 확인할 수 있다.

이 때 show processlist 명령어로 확인해 보면 Loading of data about xxx.x% done 이라고 표시된다.
여기서 나타나는 백분율은
  1. 파티션되지 않은 테이블일 때는 테이블과 테이블에 포함된 인덱스(n) 전체의 진행 사항에 에 대한 백분율을 나타낸다.
  2. 파티션된 테이블일 때는 각 파티션 별로 테이블 파티션과 파티션에 포함된 인덱스(n) 전체의 진행 사항에 대한 백분율을 나타낸다. 따라서 하나의 테이블에 2개의 파티션이 있을 경우 1~100% 까지 두 번 표시된다.

load는 인덱스 번호 순(n) > 힙 테이블 순으로 진행된다.
각 파일에 대해 위의 순서대로 B_0, B_1... 순(_db1_t1_P_PF_201401_key_cl1_t1_ad97db_1_19_B_0.tokudb, _db1_t1_P_PF_201401_key_ix1_t1_ad97db_1_19_B_1.tokudb, _db1_t1_P_PF_201401_main_ad97db_1_19_B_2.tokudb)으로 임시 파일을 만들어 loading을 한 다음 전체 loading 작업이 완료되면 원래 파일과 바꿔치기를 하고 원래 파일을 삭제한다.

-rwxrwx--x 1 mysql dba 32K 7 25 06:31 _db1_t1_P_PF_201401_key_cl1_t1_ad97c0_3_19.tokudb
-rwxrwx--x 1 mysql dba 32K 7 25 06:31 _db1_t1_P_PF_201401_key_cl1_t1_ad97db_1_19_B_0.tokudb
-rwxrwx--x 1 mysql dba 32K 7 25 06:31 _db1_t1_P_PF_201401_key_ix1_t1_ad97c0_4_19.tokudb
-rwxrwx--x 1 mysql dba 32K 7 25 06:31 _db1_t1_P_PF_201401_key_ix1_t1_ad97db_1_19_B_1.tokudb
-rwxrwx--x 1 mysql dba 32K 7 25 06:31 _db1_t1_P_PF_201401_main_ad97c0_2_19.tokudb
-rwxrwx--x 1 mysql dba 32K 7 25 06:31 _db1_t1_P_PF_201401_main_ad97db_1_19_B_2.tokudb
-rwxrwx--x 1 mysql dba 64K 7 25 07:12 _db1_t1_P_PF_201401_status_ad97c0_1_19.tokudb

참고로 파일 이름은 TokuDB 7.1.6에서는 통상적으로
  1. 메타 데이터 파일: _<데이터베이스명>_<테이블명>_[파티션명]_status_<xxx>_1_19.tokudb
  2. 힙 테이블: _<데이터베이스명>_<테이블명>_[파티션명]_main_<xxx>_2_19.tokudb
  3. 인덱스 파일: _<데이터베이스명>_<테이블명>_[파티션명]_<인덱스명>_<xxx>_[3~n]_19.tokudb
으로 생성된다.

댓글 없음:

댓글 쓰기