entry (~70k 行)、tag (~27k 行)、entry_tag (~2.5M 行)の 3 つのテーブルがある単純な SQL テーブル構造があります。entry_tag -tableには、このentry_tag ( entry_id、tag_id、... )のようなエントリとタグ間の関係 (nn 関係) が含まれています。
特定のタグを持つすべてのentry_idを最初に取得しようとしたとき、次のようなクエリを作成しました
SELECT entry_id FROM entry_tag et, tag t
WHERE t.id=et.tag_id AND t.name LIKE 'Something';
明らかな理由もなく、Win7 x64 (i5-2500K、8GB RAM、7200rpm hdd) 上の Adobe Air アプリでクエリに 6 秒以上かかりました。これは遅すぎます (特に複雑なINTERSECT
クエリの場合)。SQLite コマンド ライン ツールでは、クエリはすぐに結果を返しました。cli と Air (Air ベースの SQLite Sorcerer を使用)を比較EXPLAIN
し、結果は同じでした。EXPLAIN QUERY PLAN
どちらのクエリもインデックスを使用していました。
テーブルの順序を入れ替えてクエリを再構築した後、Air でのパフォーマンスは 250 ミリ秒に倍増しました。これは満足のいくものです。
SELECT entry_id FROM tag t, entry_tag et
WHERE et.tag_id=t.id AND t.name LIKE 'Something';
では、なぜ cli ツールが Adobe Air 環境よりもはるかに高速なのか疑問に思っていました。背景情報として、PHP で db ファイルを生成しました (すべての列INTEGER
またはTEXT
)。
元のスロー クエリのクエリ プランは次のとおりです。
sele order from deta
---- ------------- ---- ----
0 0 0 SCAN TABLE entry_tag AS et USING INDEX idx_et_eid (~1000000 rows)
0 1 1 SEARCH TABLE tag AS t USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
(〜1000000行はとにかく悪いように見えます;)