在我们公司,我们有一个相当大的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 *'”比两个比较简单。 –