2016-04-15 30 views
0

私たちの会社では、かなり大きなSQLite3データベースを持っています。データベースは一度作成され、モバイルユーザーアプリケーションでは読み取り専用モードで使用されます。SQLite3で重複データを避けるためにインデックスをカバー

POIには、発音区別記号付きの複数の単語と文字を含む名前があります。アプリケーションでPOIのクイック検索を実行するには、大文字のASCII単語を1つ追加し、メインテーブルに対応するIDを持つ追加のテーブルがあります。インデックスをカバーするがあります。

CREATE TABLE poi(id INTEGER PRIMARY KEY, name TEXT, attributes TEXT); 
CREATE TABLE poi_search (word TEXT, poi_id INTEGER); 
CREATE INDEX poi_search_idx ON poi_search(word, poi_id); 

その後、あなたはその名をそのような要求に"FOO"が含まれているPOIを照会することができます:

SELECT * from poi INNER JOIN poi_search ON poi.id=poi_search.poi_id 
    WHERE poi_search.word < 'FOO' AND poi_search.word < 'FOP'; 

クエリは非常に迅速で、カバーを使用するデータベースは、この(簡体字)のように見えますインデックス、それがすべてでpoi_searchのテーブルにアクセスする必要がないように:

sqlite> EXPLAIN QUERY PLAN SELECT * from poi INNER JOIN poi_search ON poi.id=poi_search.poi_id WHERE poi_search.word < 'FOO' AND poi_search.word < 'FOP'; 
0|0|1|SEARCH TABLE poi_search USING COVERING INDEX poi_search_idx (word<?) 
0|1|0|SEARCH TABLE poi USING INTEGER PRIMARY KEY (rowid=?) 

私はちょうど実現カバー索引は索引表のすべてのデータを複製するため、これはスペースの大きな無駄です。このアプリケーションでは、表poi_searchは実際にはであり、決してが使用されています。

覆いのインデックスのすべてのデータを保持しながらpoi_searchテーブルを削除または切り捨てる方法は、難しいものですか?私はそのようなデータベースは非コヒレントな状態にあることを知っているので、公式のAPIでこのようなハッキングを行う方法はないでしょう。

データベースの制作にSQLite3のハッキングされたバージョンは気にしません。 DBは、バニラSQLite3クライアントでの要求に対して正しい検索値を生成する必要があります。

+1

「単語[GLOB](http://www.sqlite.org/lang_expr.html#like) ': あなたは、一貫性のあるデータベースを保持することが保証されてdocumented way、で済まさなければならないだろうFOO * ''は2つの比較より簡単です。 –

答えて

1

あなたが望むことをやるためには、やりにくい方法やハックはありません。

CREATE TABLE poi_search (
    word TEXT PRIMARY KEY, 
    poi_id INTEGER 
) WITHOUT ROWID; 
-- no other index needed 
+0

ありがとうございます。 SQLite3がROWIDのないテーブルをサポートしていて、テキスト列をプライマリインデックスとしてサポートしていることはわかりませんでした。 – prapin

関連する問題