11

我有一张表,我在上面创建了全文目录。该表只有 6000 多行。我在索引中添加了两列。第一个可以被认为是唯一的排序标识符,第二个可以被认为是该项目的内容(我的表中还有 11 个其他列属于全文目录)。这是几行的示例:

TABLE: data_variables
ROW    unique_id    label
1      A100d1       Personal preference of online shopping sites
2      A100d2       Shopping behaviors for adults in household

在前端的 Web 应用程序中,我有一个文本框,用户可以输入该文本框以获取与他们在UNIQUE IDorLABEL列中搜索的任何术语匹配的项目列表。因此,例如,如果用户输入shoa100然后将使用上述两行填充列表。如果他们输入,behav则列表将仅填充上面的第 2 行。

这是通过对每个keyup. PHP 调用 SQL 服务器上的存储过程,如下所示:

SELECT TOP 50 dv.id, dv.id + ': ' + dv.label, 
              dv.type_id, dv.grouping, dv.friendly_label
FROM          data_variables dv
WHERE         (CONTAINS((dv.unique_id, dv.label), @search))

@search是传递给存储过程的用户文本。)

我注意到这变得非常缓慢,尤其是当我没有TOP 50在查询中使用时。

我正在寻找的是一种直接在 SQL Server 上或通过放弃全文索引的想法并使用 jQuery 来搜索客户端上的可搜索项数组来加快速度的方法。我已经研究了一些 jQuery AutoComplete 的东西和其他一些用于 AutoComplete 的 jQuery 插件,但还没有尝试模拟任何东西。那将是我的下一步,但我想先在这里查看一下我会得到什么建议。

提前致谢。

4

5 回答 5

6

几个建议,基于你只有 6000 行的事实,所以数据库应该活着吃掉这个。

A. 尝试使用 Like 运算符,以防万一。也不期待它,但尝试起来很简单。考虑到这些小体积,总体而言,这里还有其他事情让您检测到这很慢。

B. 可以提前缓存查询吗?对于 6000 行,可能只有 36*36 的 2 个字符查询组合,这几乎不占用内存并为数据库节省任何工作。

C. 将选择移到客户端是一个好主意,这取决于 6000 行的总体大小,以及单个查找的网络延迟。

D. 我怀疑将 b 和 c 结合起来会给你带来非常好的性能,但需要一些编码工作。如果服务器在缓存中维护所有单个字符结果的列表,并且客户端在第一次击键后下载字母缓存集,那么它们可能拥有所有行的子集,但不需要为额外的击键执行更多网络 IO。

于 2013-03-02T19:57:54.703 回答
6

我建议不要使用 LIKE,除非您使用线性索引(从左到右)并且您正在执行类似LIKE 'work%'. 如果您正在执行LIKE '%word%'常规索引之类的操作,则对您没有帮助。当您想要在段落中搜索单词时,您通常想要使用全文索引。

对于大量数据,通常数据库中内置的全文引擎并不是很窃取。为了获得最佳性能,您通常必须使用专为全文构建的外部解决方案。

一些选项是SphinxSolrelasticsearch,仅举几例。我不会说这些选项中的任何一个都比另一个更好。肯定有优点和缺点需要考虑:

  • 你有什么样的数据?
  • 这些解决方案有哪些语言支持?
  • 这些解决方案支持哪些数据库引擎?

您可以做的最好的事情是根据您现有的数据对这些解决方案进行基准测试。测试每个单独的组件(单元测​​试)可以帮助您识别真正的问题并帮助您找到好的解决方案。

于 2013-03-08T18:50:37.670 回答
5

我遇到了同样的问题并选择了 LIKE 解决方案。我也发现 or 运算符太费力了,并将查询分成两个选择,并使用一个 union all(最快,在我的场景中,不可能在索引列和数据中找到相同的文本)。

你的会像

SELECT TOP 50 from (
select dv.id, dv.id + ': ' + dv.label, 
              dv.type_id, dv.grouping, dv.friendly_label
FROM          data_variables dv
WHERE         dv.unique_id like '%'+@search+'%'
UNION ALL
select dv.id, dv.id + ': ' + dv.label, 
              dv.type_id, dv.grouping, dv.friendly_label
FROM          data_variables dv
WHERE         dv.label like '%'+@search+'%' 
)

哦!!并在 SQL Server 中测试性能,而不是在 Web 中!

于 2013-03-07T10:55:48.777 回答
2

如果您计划增加数据量,最好使用反向索引进行全文搜索。

看看Apache Solr - 目前最好的全文搜索引擎。

您可以简单地定期索引您的数据库数据并使用 solr 作为搜索引擎,它提供简单的 ajax api,可以直接从前端查询。

于 2013-03-06T16:03:13.170 回答
0

如果你真的需要性能..你可能想看看;FTS3 和 FTS4 ...

截图...来自另一个论坛...

例如,如果将“安然电子邮件数据集”中的 517430 个文档中的每一个都插入到 FTS 表和使用以下 SQL 脚本创建的普通 SQLite 表中:

代码:使用 fts3(内容文本)创建虚拟表 enrondata1;/* FTS3 表/ CREATE TABLE enrondata2(content TEXT); /普通表 */ 然后可以执行下面两个查询中的任何一个来查找数据库中包含单词“linux”(351)的文档的数量。使用一台台式 PC 硬件配置,对 FTS3 表的查询在大约 0.03 秒内返回,而查询普通表则为 22.5 秒。

看...

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

于 2013-03-09T15:10:05.787 回答