桜、抹茶、白、日記

名古屋市在住のC++使いのcoderの日記だったもの。

SQLiteではまる

d:id:youandi:20070531#p3
今日は丸っとSQLiteではまりっぱなしで1日終わったorz

DBへのINSERT処理が500msecも掛かるので調査

結局自分が実装したトランザクション処理で「BEGIN;」と書くべき所を「COMMIT;」って書いていてバグっていたorz

やっぱり妙にディスクアクセスが多い

SQLiteのファイルDBではやっぱりmsecオーダーでの処理に耐えられないのか・・・orz

in-memoryDBに変更して処理後にファイルDBに落とす

実行環境によってCPUの使用率が異なるというか、一番速いマシン(C2D 6850)で50%前後、自分のマシン(C2D 6400)で10%未満。それ以外の環境でも10%未満。HDDのベンチマークでは2倍以上の差があるので、やはりディスクアクセスがネックだろうと言う事で変更。

    1. in-memoryDB(DBのパスに":memory:"を指定)で処理実行しデータを登録
    2. ファイルDBの殻(DB作成、テーブル作成)を用意
    3. 下の処理を実行

マスターDBからテーブル名一覧を取得して、

SELECT name FROM sqlite_master WHERE type = 'table'

パラメータ置換でクエリー文を生成しようにも、INSERT INTO直後のパラメータが必ずエラーで実行できないorz

ATTACH DATABESE ? AS ?;
INSERT INTO ?.? SELECT * FROM ?;
DETACH DATABESE ?

とりあえずテーブル毎にsnprintfを使ってベタでクエリー文を生成するようにしました。

--ファイルDBをアタッチ
ATTACH DATABESE 'C:\hoge\data.db' AS DB1;
--ファイルDBのテーブルにデータを登録
INSERT INTO DB1.TABLE1 SELECT * FROM TABLE1;
--〜テーブル数分繰り返し〜
INSERT INTO DB1.TABLEnnn SELECT * FROM TABLEnnn;
--ファイルDBをデタッチ
DETACH DATABESE DB1

大量のデータがある場合に上記の処理がどれ位の時間が掛かるかは未調査ですが、とりあえずちゃんと動作していました。

SQLite が認識できる SQL > COPY
http://www.net-newbie.com/sqlite/lang.html#copy

上記のサイトを見る限り、もっと簡単にできそうな構文があったのですが、in-memoryDBの場合に「ファイル名」の指定部分にパスの書きようが無さげなのでINSERT文使うしかない鴨。
こんな事をしていたら、20時には帰るつもりが結局定時を過ぎていましたorz


もうため息と咳と不具合しかでないな・・・。