10

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

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

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

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

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

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

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

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

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

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

4

4 回答 4

10

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

例如,假设“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 相比的优点是您不必在数据中添加空格,这会不必要地增加数据库的大小。

The disadvantage is that you have to implement the custom tokenizer. Fortunately, I have one ready for you. The code is in C, so you have to figure out how to integrate it with your Java code.

于 2013-04-02T02:09:26.287 回答
3

您应该为数据库上的列添加一个索引name,这应该会大大加快查询速度。

我相信 SQLite3 支持这样的子字符串匹配:

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

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

于 2012-07-04T20:48:22.950 回答
0

I am facing some thing similar to your problem. Here is my suggestion try creating a translation table that will translate all the words to numbers. Then search numbers instead of words.

Please let me know if this is helping.

于 2013-04-03T21:18:25.793 回答
-1

由于您使用的是 sqllite,因此不确定是否要加快速度,但是对于子字符串搜索,我做了类似的事情

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

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

于 2012-07-04T20:06:08.847 回答