在我們公司,我們有一個相當大的SQLite3數據庫,比方說一些興趣點(POI)。數據庫只創建一次,並在移動用戶應用程序中以只讀模式使用。避免在SQLite3中使用覆蓋索引重複數據
POI的名稱可以包含幾個帶有變音符的單詞和字母。要在應用程序中執行POI的快速搜索,有一個附加的表格,其中包含單個大寫ASCII字詞和主表中相應的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);
然後,您可以查詢POI有了這樣的請求,其名稱包含"FOO"
:
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的黑客版本的數據庫的生產;但數據庫必須在香草SQLite3客戶端中爲給定請求生成正確的搜索值。
「字[GLOB(http://www.sqlite.org/lang_expr.html#like)' 「FOO *'」比兩個比較簡單。 –