日記帳

日記です。

SQLite にデータを入れる際にインデックスを作ってからインポートするか,インポートしてからインデックスをつくるか

仕事で1000万件ほどのデータをSQLite にインポートしていたのですがなかなか処理が終りません…

CSV ファイルなどに大量にあるデータをまとめて SQLite のDB にインポートするとします. インポート先のテーブルにはいくつかインデックスをつけたいとします.

こういう場合に,インデックスをつけたテーブルをつくってそこにインポートするのと, テーブルだけつくってデータをインポートしてから改めてインデックスをつくるのとではどちらが速いでしょうか?

普通に考えればインポートしてからまとめてインデックスを作成した方が速くなりそうだと想像はつくのですが,実際のところどうなのでしょう? 速くなるとしたら何%くらい違うのでしょうか?

ということで実測してみました.

(511) cat create-table.sql 
CREATE TABLE Logs(
	ID INTEGER PRIMARY KEY
,	LogTime DATETIME
,	LogLevel TEXT
,	Message TEXT
);
(512) cat create-index.sql 
CREATE INDEX Logs_ID_IDX ON Logs(ID);
CREATE INDEX Logs_LogTime_IDX ON Logs(LogTime);
(513) cat bench_create_index_and_insert.sh
DBFILE=Logs.sqlite
DATA_FILE=$1
sqlite3 ${DBFILE} < create-table.sql
sqlite3 ${DBFILE} < create-index.sql
sqlite3 -separator "	" ${DBFILE} ".import ${DATA_FILE} Logs"
(514) cat bench_insert_and_create_index.sh
DBFILE=Logs.sqlite
DATA_FILE=$1
sqlite3 ${DBFILE} < create-table.sql
sqlite3 -separator "	" ${DBFILE} ".import ${DATA_FILE} Logs"
sqlite3 ${DBFILE} < create-index.sql
  • A:インデックス作成→インポート
  • B:インポート→インデックス作成
データ数 A(秒) B(秒) B/A(%)
100000 3.673 2.504 68.173
200000 9.724 6.598 67.853
300000 14.682 11.693 79.642
400000 22.097 16.972 76.807
500000 29.678 23.148 77.997
600000 36.227 28.596 78.936
700000 42.295 34.468 81.494
800000 51.668 40.596 78.571
900000 58.526 47.404 80.996
1000000 63.243 53.073 83.919


予想通りですが全体的にインポートしてからインデックス作成をする方が速いようですね. 10万件のインポートだとその差は約 30% .しかしデータが増えるにつれて差が減ってきて 100万件になると20%程度の差になります.

1000万件ほどになると大きな差はないのかもしれませんね… ということで処理が終わるのをのんびり待つことにします…

以下テスト環境について.

(503) uname -a
Darwin himane.local 10.2.0 Darwin Kernel Version 10.2.0: Tue Nov  3 10:37:10 PST 2009; root:xnu-1486.2.11~1/RELEASE_I386 i386
sawai@himane[22:41:43] ~
(504) sqlite3 -version
3.6.22