効果の程はどうでしょうね〜
これに対抗してシェルスクリプトだけでLOAD DATAを小刻みに行うコードを書いてみます。
中途半端な引数だったり、MySQL関連の変数がベタ書きだったり、ファイル名は「テーブル名.tsv」固定なのは勘弁して下さい。
#/bin/sh filePath=$1 splitLineCount=$2 schemaName=$3 dir="/Users/tree" USAGE="Usage:<filePath> <splitLineCount> <schemaName>" if [ -z $filePath ] || [ -z $splitLineCount ] || [ -z $schemaName ]; then echo "$USAGE" exit 1 fi echo "bulk load data start." # file split fileRegex="$filePath\.*" rm -rf $fileRegex split -l $splitLineCount $filePath $filePath. splitFileCount=$(ls $fileRegex | wc -l) # mysql setting tableName="$(echo $(basename $filePath) | cut -d'.' -f1)" MYSQL_CON="mysql -uroot $schemaName" FIELDS_TERMINATED_BY="\t" ENCLOSED_BY="" LINES_TERMINATED_BY="\n" count=1 # truncate $MYSQL_CON -e "truncate $tableName;" # bulk load data for file in `ls $fileRegex` do $MYSQL_CON <<EOF alter table $tableName disable keys; load data infile "$dir/$file" into table $tableName fields terminated by "$FIELDS_TERMINATED_BY" enclosed by "$ENCLOSED_BY" lines terminated by "$LINES_TERMINATED_BY"; alter table $tableName enable keys; EOF if [ $? -eq 1 ]; then echo "[$count/$splitFileCount] load data $file failure." exit 1 else echo "[$count/$splitFileCount] load data $file success." fi rm -rf $file count=$(expr $count + 1) done echo "bulk load data finish."
実行結果は以下の通りです。
$ ll bulkLoadData.sh t_test.tsv -rwxr-xr-x 1 tree staff 1193 4 14 00:40 bulkLoadData.sh -rw-r--r-- 1 tree staff 2109444 3 31 01:45 t_test.tsv $ ./bulkLoadData.sh t_test.tsv 100000 test bulk load data start. [1/4] load data t_test.tsv.aa success. [2/4] load data t_test.tsv.ab success. [3/4] load data t_test.tsv.ac success. [4/4] load data t_test.tsv.ad success. bulk load data finish.
LOAD DATAする時はDISABLE KEYSしてます。
これで巨大なファイルを読み込む時にバッファを使い切る事もなくなりますかね??
このbulkLoadData.shですが、workテーブルに対して読み込んで、データ登録完了後にworkテーブルと本番用テーブルを入れ替えた方が良さそうです。
こんな感じです↓
#!/bin/sh mysql -uroot test -e "create table t_test_work like t_test;" ./bulkLoadData.sh t_test_work.tsv 10000 test if [ $? -eq 1 ]; then exit 1 fi mysql -uroot test -e "rename table t_test to t_test_old, t_test_work to t_test;"
t_test_workまでは失敗してもt_testに全然影響無し。rename テーブルはトランザクションが有効なので、影響無く入れ替えられるはず。