2016-04-15 61 views
0

在我們公司,我們有一個相當大的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客戶端中爲給定請求生成正確的搜索值。

+1

「字[GLOB(http://www.sqlite.org/lang_expr.html#like)' 「FOO *'」比兩個比較簡單。 –

回答

1

有沒有棘手的方式,或黑客做你想做的。 你必須湊合着documented way,這是保證讓數據庫保持一致:

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

謝謝。我不知道SQLite3支持沒有rowid的表,支持將文本列作爲主索引。 – prapin