2007年10月08日

SQLite性能評価その3

SQLite性能評価その2」の続きです。 テーブルに100000件追加する処理だけでも、Case2の他にいろいろな書き方があるので、試してみました。

100000件追加処理色々

sqlite3_execの代わりにsqlite3_prepareとsqlite3_stepを使ってみました。これをCase3とします。

// Case3
struct sqlite3* Db;
struct sqlite3_stmt* Statement;
char Buffer[256];

sqlite3_open("testdb.sq3", &Db);
sqlite3_prepare(Db, "CREATE TABLE test1(name TEXT,value INTEGER)", -1, &Statement, NULL);
while (sqlite3_step(Statement) == SQLITE_BUSY);
sqlite3_finalize(Statement);
// 処理時間測定開始
sqlite3_prepare(Db, "BEGIN", -1, &Statement, NULL);
while (sqlite3_step(Statement) == SQLITE_BUSY);
sqlite3_finalize(Statement);
for (int i = 0; i < 100000; ++i) {
  char* Sql = sqlite3_snprintf(sizeof(Buffer), Buffer, "INSERT INTO test1 VALUES('%q',%d)", StringList[i].c_str(), ValueList[i]);
  sqlite3_prepare(Db, Sql, -1, &Statement, NULL);
  while (sqlite3_step(Statement) == SQLITE_BUSY);
  sqlite3_finalize(Statement);
}
sqlite3_prepare(Db, "COMMIT", -1, &Statement, NULL);
while (sqlite3_step(Statement) == SQLITE_BUSY);
sqlite3_finalize(Statement);
// 処理時間測定終了
sqlite3_close(Db);

sqlite3_prepare の真価」で紹介されている方法を使ってみました。 これをCase4とします。

// Case4
struct sqlite3* Db;
struct sqlite3_stmt* Statement;

sqlite3_open("testdb.sq3", &Db);
sqlite3_prepare(Db, "CREATE TABLE test1(name TEXT,value INTEGER)", -1, &Statement, NULL);
while (sqlite3_step(Statement) == SQLITE_BUSY);
sqlite3_finalize(Statement);
// 処理時間測定開始
sqlite3_prepare(Db, "BEGIN", -1, &Statement, NULL);
while (sqlite3_step(Statement) == SQLITE_BUSY);
sqlite3_finalize(Statement);
sqlite3_prepare(Db, "INSERT INTO test1 VALUES(?,?)", -1, &Statement, NULL);
for (int i = 0; i < 100000; ++i) {
  sqlite3_reset(Statement);
  sqlite3_bind_text(Statement, 1, StringList[i].c_str(), static_cast<int>(StringList[i].size()), SQLITE_TRANSIENT);
  sqlite3_bind_int(Statement, 2, ValueList[i]);
  while (sqlite3_step(Statement) == SQLITE_BUSY);
}
sqlite3_finalize(Statement);
sqlite3_prepare(Db, "COMMIT", -1, &Statement, NULL);
while (sqlite3_step(Statement) == SQLITE_BUSY);
sqlite3_finalize(Statement);
// 処理時間測定終了
sqlite3_close(Db);

Case4のsqlite3_prepareをsqlite3_prepare_v2に変えてみました。これをCase5とします。

// Case5
struct sqlite3* Db;
struct sqlite3_stmt* Statement;

sqlite3_open("testdb.sq3", &Db);
sqlite3_prepare_v2(Db, "CREATE TABLE test1(name TEXT,value INTEGER)", -1, &Statement, NULL);
while (sqlite3_step(Statement) == SQLITE_BUSY);
sqlite3_finalize(Statement);
// 処理時間測定開始
sqlite3_prepare_v2(Db, "BEGIN", -1, &Statement, NULL);
while (sqlite3_step(Statement) == SQLITE_BUSY);
sqlite3_finalize(Statement);
sqlite3_prepare_v2(Db, "INSERT INTO test1 VALUES(?,?)", -1, &Statement, NULL);
for (int i = 0; i < 100000; ++i) {
  sqlite3_reset(Statement);
  sqlite3_bind_text(Statement, 1, StringList[i].c_str(), static_cast<int>(StringList[i].size()), SQLITE_TRANSIENT);
  sqlite3_bind_int(Statement, 2, ValueList[i]);
  while (sqlite3_step(Statement) == SQLITE_BUSY);
}
sqlite3_finalize(Statement);
sqlite3_prepare_v2(Db, "COMMIT", -1, &Statement, NULL);
while (sqlite3_step(Statement) == SQLITE_BUSY);
sqlite3_finalize(Statement);
// 処理時間測定終了
sqlite3_close(Db);

測定結果

測定結果は以下のようになりました。
処理時間

分かったこと。

  • Case2とCase3のほとんど同じです。sqlite3_execで済むときはこれを使えば良いでしょう。
  • Case3とCase4はだいぶ違います。処理時間が6割近く削減できています。複数のデータを追加するときは、Case4の方式を使いましょう。
  • Case4とCase5はほとんど同じです。sqlite3_prepare_v2を使うことによる速度的なメリットは無いようです。

SQLiteの性能評価その4」に続きます。

投稿者 MASATO : 2007年10月08日 16:34 | トラックバック
コメント
コメントする









名前、アドレスを登録しますか?