【问题标题】:SELECT ... WHERE Value LIKE '%...%'SELECT ... WHERE Value LIKE '%...%'
【发布时间】:2015-08-01 11:11:43
【问题描述】:

我越来越意识到提高查询效率的重要性。至关重要的是,我拥有适当的索引等,以确保我的查询不会占用比实际需要更多的 IO。但这是一个丑陋的查询,我不知道如何提高效率。

假设我有一个库存商品表,其最基本的形式如下所示:

CREATE TABLE StockItems (
  ItemID INT IDENTITY (1, 1) NOT NULL PRIMARY KEY,
  SerialNo VARCHAR (50) NOT NULL
);

现在我需要编写一个存储过程,它将返回序列号与提供的部分序列号匹配的所有库存项目。以下查询将完全实现:

SELECT * FROM StockItems WHERE SerialNo LIKE '%' + @SearchStr + '%'

但是当我看到这样的问题时,我冷汗直冒,把我的舒适毯子抓得更紧了。 SerialNo 上没有索引,即使有,考虑到我正在搜索部分匹配项,这也无济于事。

有没有办法通过更高效的查询来完成这项任务?

【问题讨论】:

  • 如果您希望它是部分匹配,恐怕没有其他方法可以做到这一点(那会更有效)。
  • 这可能会有所帮助:stackoverflow.com/questions/7510646/…
  • 有很多方法可以优化这样的查询,但实际上并没有那么多只涉及在表上塞入某种内置索引类型。例如,您可以将书名分解为所有单词,删除干扰词(the、and、or 等)并存储一个包含这些单词的单独表格,并将它们链接到包含这些单词的所有书名。然后,您将首先对这些行进行查询,然后使用 LIKE 表达式来获得正确的部分匹配。
  • 这些场景当然是有效的,如果你能够实现Full-text Index,你可以提高查询性能:msdn.microsoft.com/en-us/library/…technet.microsoft.com/en-us/library/ms187787(v=sql.105).aspx
  • Amazon 和人们通常使用全文索引——这与搜索完全匹配的部分不同(例如,您可以在“照顾树木”中找到“tree”,但不能在“tre”中找到或“汽车”)。如果您能想到任何分区,您可以添加自己的分区 - 但like '%XXX%' 几乎不可能以任何有意义的方式进行索引。并且索引仍然可以帮助 I/O——而不是遍历表中的所有数据,它只需要扫描索引——如果索引比表小得多,这是值得的。但仅此而已。 %XXXX% 都很好,但 %XX% 很疯狂。

标签: sql sql-server


【解决方案1】:

在文本中搜索单词的问题与在序列号中快速搜索子字符串的问题有很大不同。例如,倒排索引是文本分析的一个组成部分,但要了解这些如何应用于您的问题就不太明显了。

您的问题是这在实践中是如何完成的。一种简单的方法是硬件。在数据库环境中,这会将包含序列号的表固定到内存中(如果表被大量使用并且不太大,默认情况下会发生这种情况)然后进行扫描。使用更多线程/处理器可以更快地进行扫描,因此将硬件投入到问题上会有所帮助。

编写自定义代码(亚马逊或谷歌就是这种情况)会使这个过程更快。

还有其他解决方案。如果字符串较大,则可以使用 n-gram 对字符串进行编码。 N-gram(在这种情况下)是出现在字符串中的字符序列,比如 3 长(更多 information)。

对于每个序列号,您分解所有 n-gram 序列并将它们存储在一个大的索引表中。然后在搜索字符串中查找所有 n-gram。首先,只获取具有相同 n-gram 集的序列号。然后对其进行蛮力搜索。

例如,如果您的序列号为“1234567890”,则它具有以下三元组:123、234、456、567、678、789、890

如果您正在搜索%1919%,那么任何匹配的字符串都需要有 191 和 919。第一个字符串都没有,所以您不需要搜索它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 2011-11-28
    • 2019-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多