02 April
2004

SQLite の INSERT は遅いのか?

MySQLとSQLite(PrinCo.)という記事経由で、生まれ変わるPHP - Zend Engine 2、SQLiteの実力は?(MYCOM PC WEB)という記事を読んだ。

MySQL と SQLite で INSERT 時の処理速度が公開されている。 1000件のレコードのINSERTを実行し、それぞれにどれぐらいの時間がかかっているかを示しているのだ。

MySQLが 0.4秒、SQLite が 16秒だというのだが、これはあまりにもひどすぎる。しかも、結論としてどうやら大量データの連続挿入はSQLiteの不得意な処理のようだ。と書かれている。1000件程度でこんなにかかるんだったら、10000件だったら160秒ぐらいかかる(単純すぎ。)って事?

実はこれにはからくりがあって、SQLite の処理は トランザクション の中でないと著しく遅いのだ。おそらく、これが原因なのではないかと思っている。


上記記事のベンチマーク結果を覆す事は出来ない(PHP5 と MySQL が、私の環境では使えていない)のだが、トランザクションを使った場合と、使わなかった場合の処理速度の違いを示す事は出来る。C言語で同じような処理を行うプログラムを作って、その処理時間を調べてみた。まずは、トランザクションを使った場合。

% /usr/bin/time -h ./instest 
        0.41s real              0.06s user              0.00s sys

すばらしい処理時間(0.4秒)だ。
次に使わなかった場合。

% /usr/bin/time -h ./instest 
        3m19.09s real           0.43s user              1.25s sys

私のプログラムがヘボイのか、記事の結果とあまりにも違いすぎる(3分ってどういう事?)のが気になる。しかし、ここでわかる事は SQLite での処理は、トランザクションが必要だろうという事だ。これは、SQLiteが、複数のプロセスからのアクセスがあっても データベースファイルが壊れないように、1件づつの処理で色々とやっているからだろう。以前調べた事だが、トランザクション中は、別のプロセスがファイルにアクセスしようとしてもロックされた状態になる。トランザクション中は書き放題なので速いのだろう。

最後に、今回の実験に利用したプログラムのソースコードを載せておく。

 
#include <stdio.h> 
#include <sqlite.h> 
 
#define INSERT_COUNT 1000 
 
int main(int argc, char *argv[]) 
{ 
  sqlite *db; 
  char *errmsg; 
  int i; 
 
  /* SQLite データベースを OPEN */ 
  db = sqlite_open("instest.db", 0755, &errmsg); 
  if (!db) { 
    printf("%s: %s\n", argv[0], errmsg); 
    exit(-1); 
  } 
 
  /* BEGIN TRANSACTION */ 
#ifdef USE_TRANSACTION 
  (void)sqlite_exec(db, "BEGIN", NULL, NULL, &errmsg); 
#endif 
 
  /* INSERT */ 
  for (i = 0; i < INSERT_COUNT; i++) { 
    char *sql; 
 
    sql = sqlite_mprintf("INSERT INTO test VALUES (%d)", i); 
    (void)sqlite_exec(db, sql, NULL, NULL, &errmsg); 
  } 
 
  /* COMMIT TRANSACTION */ 
#ifdef USE_TRANSACTION 
  (void)sqlite_exec(db, "COMMIT", NULL, NULL, &errmsg); 
#endif 
 
  sqlite_close(db); 
} 
Posted by Satoshi at 04:15 | Comments (4) | Trackbacks (0) | このエントリーを含むはてなブックマーク
Comments
Re: SQLite の INSERT は遅いのか?

トランザクション無しのSQLiteが遅いという話は探したら結構あるみたいですね。
しかし、トランザクションかけると随分と早いですね。型が無いとか、既存のRDBMSと異なる部分も多いみたいですが、その辺こなれてくると本当に便利そうですね、SQLite。

そしてその辺の使い方はPHPコミュニティが確立してくれることを勝手に期待。

Posted by: hine at April 04,2004 16:57
Re: SQLite の INSERT は遅いのか?

型がないことのメリットっていまいち良くわかってなかったりするんですが。。。。。。
ライセンスや使いやすさを考えると、単体のアプリケーション作るには必需品になりそうですね。

Posted by: Satoshi at April 06,2004 00:16
Re: SQLite の INSERT は遅いのか?

記事に訂正文が追加されてますね。
やはりSQLiteの方がINSERT早いみたいです。

Posted by: halt at April 18,2004 00:40
Re: SQLite の INSERT は遅いのか?

halt さん。情報ありがとうございます。
さっそく、訂正文を確認しました。たしかに MySQL よりも速いみたいですね。

SQLite の構造上、同時アクセスは不利ですが、ほとんどアクセスの無いサイトを作る場合とかには MySQL よりもこちらを使うほうが良いかもしれませんね。

Posted by: Satoshi at April 18,2004 11:13
Re: SQLite の INSERT は遅いのか?

こちらのエントリを参考にさせていただきました。おそらくcomitのたびにfsyncしまくっているのですが、ファイルシステム構成によってもかなり影響を受けるようです。

http://www.sqlite.org/speed.html のTest 1を再現してみるとこんな感じになります。
SUSE 9.1 ReiserFS: 35.390sec
SUSE 9.1 ReiserFS(trans): 0.241sec
Fedora Core 2 Ext3: 11.202sec
Fedora Core 2 Ext3(trans): 0.386sec

Posted by: (o) at August 28,2004 09:38
Re: SQLite の INSERT は遅いのか?

コメントありがとうございます。そして返事が遅くなり申し訳ございません。

なるほど、fsync ですね。データベースは内容を保証しなければなりませんから、毎回ファイルに書き込むと言う事なのでしょうね。

こちらこそ為になりました。

Posted by: Satoshi at September 10,2004 00:07
Re: SQLite の INSERT は遅いのか?

もしご存知でしたら教えてほしいのですが
SQLiteにMySQLのLOAD FILE のような一括インポートコマンドはあるでしょうか?
また早いでしょうか?
MySQLで大量データだとINSERTではなくLOAD FILEでTAB形式を取り込む場合が多いので。

Posted by: matchori at September 21,2004 19:40
Re: SQLite の INSERT は遅いのか?

matchori さん。返事が遅くなって申し訳ない。
一括インポートコマンドがあるかどうか、今はちょっとわかりません。時間が出来たら調べてみたいと思います。

もしお困りでしたら、どこかの(巨大)掲示板みたいなところで質問されたほうが良いかもしれません。ここはあんまりアクセスが無いので。

Posted by: Satoshi at September 24,2004 02:25
Trackbacks
Please send trackback to:http://www.randynetwork.com/blog/87/tbping
SQLiteをMovable Typeで使ってみる

「Movable Typeのマイナー機能を使ってみる」シリーズ第二弾。第一弾は「Ogawa::Memoranda: mt-view.cgiを使ってみる。」。 あまり知られていないことですが、MT3.1の「テンプレートごとに管理可能なダイナミックPHPページ生成」機能はBerkeleyDBでは動作しません。3.1でこの機能を使いたい人はMySQLかPostgreSQLかSQLiteにとっとと移行する必要があります。 このうち、MySQL、PostgreSQLは三層Webアプリケーション構築においてはごくメジャー(かつ安価)なソリューションである一方、計算機に親しみ切れていない人々にとっては取っ付きの悪いのも事実です。そこで考えてみたいのは、やはりSQLiteっていうのは何なのかということです。 SQLite home page PHP5に標準でバンドルされるようになったのでご存知の方も多いと...

Posted by: Ogawa::Memoranda at August 26,2004 18:28
[mac]SQLite3をC言語で使う練習。

ちょうどよい記事を見つけてしまったので練習してみる。 元祖 サトシのブログ:「SQLite の INSERT は遅いのか?」 簡潔なテストコード。ちょっと拝借してSQLite3用に手直し。環境は、 iBook G4 Mac OSX 10.4.8 適当なフォルダに以下のファイルを作成。 instest.c #include

Posted by: 与太郎プログラマの日記 at December 07,2006 22:54
Post a comment