SQLite:大表中的高效子字符串搜索

时间:2012-07-04 19:58:59

标签: android sqlite fts3

我正在开发一个Android应用程序,它必须在一个大表中执行子字符串搜索(大约500,000个带有街道和位置名称的条目,所以每个条目只有几个单词)。

CREATE TABLE Elements (elementID INTEGER, type INTEGER, name TEXT, data BLOB)

请注意,只有20%的条目在“name”列中包含字符串。

执行以下查询几乎需要2分钟:

SELECT elementID, name FROM Elements WHERE name LIKE %foo%

我现在尝试使用FTS3来加速查询。这非常成功,查询时间减少到1分钟(令人惊讶的是,数据库文件大小仅增加了5%,这对我来说也很好。)

问题是,FTS3似乎不支持子串搜索,即如果我想在“foo bar”和“foobar”中找到“bar”,我只会得到“foo bar”,尽管我需要两个结果。 / p>

所以实际上我有两个问题:

  1. 是否可以进一步加快查询速度?我的目标是查询30秒,但我不知道这是否真实......

  2. 如何使用FTS3进行真正的子字符串搜索?

4 个答案:

答案 0 :(得分:10)

解决方案1: 如果您可以将数据库中的每个字符作为单个单词,则可以使用phrase queries来搜索子字符串。

例如,假设“my_table”包含单个列“person”:

person
------
John Doe
Jane Doe

您可以将其更改为

person
------
J o h n D o e
J a n e D o e

要搜索子字符串“ohn”,请使用短语查询:

SELECT * FROM my_table WHERE person MATCH '"o h n"'

请注意“JohnD”将匹配“John Doe”,这可能是不合需要的。 要修复它,请将原始字符串中的空格字符更改为其他字符。

例如,您可以使用“$”替换空格字符:

person
------
J o h n $ D o e
J a n e $ D o e

解决方案2: 按照解决方案1的想法,您可以使用自定义标记生成器将每个字符作为单个单词,并使用短语查询来查询子字符串。

优于解决方案1的优势在于您不必在数据中添加空格,这可能会不必要地增加数据库的大小。

缺点是您必须实现自定义标记生成器。幸运的是,我有one ready for you。代码在C中,因此您必须弄清楚如何将它与Java代码集成。

答案 1 :(得分:3)

您应该在数据库的name列中添加索引,这样可以大大加快查询速度。

我相信SQLite3支持子字符串匹配,如下所示:

SELECT * FROM Elements WHERE name MATCH '*foo*';

http://www.sqlite.org/fts3.html#section_3

答案 2 :(得分:0)

我正面临着与你的问题相似的一些事情。这是我的建议尝试创建一个将所有单词翻译成数字的翻译表。然后搜索数字而不是单词。

如果这有帮助,请告诉我。

答案 3 :(得分:-1)

不确定加速,因为你使用sqllite,但对于子字符串搜索,我做过像

这样的事情
SET @foo_bar = 'foo bar'
SELECT * FROM table WHERE name LIKE '%' + REPLACE(@foo_bar, ' ', '%') + '%'

当然这只返回在单词“bar”之前有“foo”字样的记录。