【问题标题】:LIKE vs CONTAINS on SQL ServerSQL Server 上的 LIKE 与 CONTAINS
【发布时间】:2011-11-22 13:31:42
【问题描述】:

以下哪个查询更快(LIKE 与 CONTAINS)?

SELECT * FROM table WHERE Column LIKE '%test%';

SELECT * FROM table WHERE Contains(Column, "test");

【问题讨论】:

  • 接受一个答案,好吗?
  • 他已经好几年没上了。

标签: sql-server performance contains sql-like


【解决方案1】:

第二个(假设你的意思是CONTAINS,实际上把它放在一个有效的查询中)应该更快,因为它可以使用一些形式的索引(在这种情况下,一个全文索引)。当然,这种查询形式只有如果列在全文索引中才可用。如果不是,则只有第一个表单可用。

使用 LIKE 的第一个查询将无法使用索引,因为它以通配符开头,因此始终需要全表扫描。


CONTAINS 查询应该是:

SELECT * FROM table WHERE CONTAINS(Column, 'test');

【讨论】:

  • @edze - 你的意思是,已经链接到我第一次提到CONTAINS的同一页面?它呢?问题的原始形式有Column CONTAIN("%test%",Column)>0,这几乎是无效的。仍然不完全正确。
  • 这帮助我们整理了关于 SharePoint 的查询。拥有另一个出色答案徽章。
【解决方案2】:

在 SQL Server 2012 实例上运行两个查询后,我可以确认第一个查询在我的情况下是最快的。

带有LIKE 关键字的查询显示了聚集索引扫描。

CONTAINS 还进行了聚集索引扫描,其中包含用于全文匹配和合并连接的附加运算符。

【讨论】:

  • 聚集索引叶页表。带有前导通配符的LIKE 查询将无法有效地使用索引部分。它只需要扫描整个东西。虽然毫无疑问,在某些情况下,完整 CI 扫描的性能优于使用全文索引的查询(例如,如果有很高比例的行匹配),这在很大程度上是例外,而不是您“可以确认的一般规则” "。
  • 好吧,我正在查看一个获取超过 200,000 条记录的实际执行计划。将两个查询放在一个批处理中,都扫描了聚集索引,但此外“CONTAINS”查询确实增加了 FULL TEXT MATCH 和 MERGE JOIN 的成本。
  • 如果选择合并连接,则 SQL Server 估计超过 x% 的行最终会匹配谓词。 (其中 X = tipping point)。在那种情况下,我想两者最终会势均力敌。执行计划中显示的成本只是估计值(即使在实际计划中也是如此)。虽然 FT 计划中有额外的执行计划运算符,但它确实有一些好处。合并连接可以在扫描结束前停止,当它用完 FT 结果时,它也不必评估LIKE
  • 我运行了一个类似的查询来检查 sql 2012 中的执行计划,它给了我一个 Index Seek。也许在这里的例子中,桌子几乎是空的。在某些情况下,sql 在非常小的表中使用索引扫描来代替使用索引,因为它更快。
【解决方案3】:

我认为CONTAINS 花费了更长的时间并使用了Merge,因为您的查询adventure-works.com 中有一个破折号(“-”)。

破折号是一个中断词,因此CONTAINS 在全文索引中搜索adventure,然后搜索works.com 并合并结果。

【讨论】:

    【解决方案4】:

    也尝试从这里改变:

        SELECT * FROM table WHERE Contains(Column, "test") > 0;
    

    到这里:

        SELECT * FROM table WHERE Contains(Column, '"*test*"') > 0;
    

    前者将查找具有“这是一个测试”和“一个测试用例是计划”之类的值的记录。

    后者还将查找具有诸如“我正在测试这个”和“这是最棒的”之类的值的记录。

    【讨论】:

    • 在搜索词前后加星号有效吗?在阅读CONTAINS 的文档时,它只提到使用像“test*”这样的前缀词,而不是像“test”这样的后缀词,而不是像“*test”这样的完整子字符串搜索。不过我还没试过。
    • 如果您阅读了 CONTAINS (docs.microsoft.com/en-us/sql/t-sql/queries/…) 的文档,则仅支持搜索前缀。我已经通过实验尝试了很多次,并且无法使用 Contains(Column, '"test"') 找到“这是最好的”(在 SQL Sever 中)
    猜你喜欢
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 2016-02-29
    • 2014-06-24
    • 1970-01-01
    • 2019-02-12
    相关资源
    最近更新 更多