【问题标题】:Does SQL Server optimize LIKE ('%%') query?SQL Server 是否优化 LIKE ('%%') 查询?
【发布时间】:2011-06-29 17:01:43
【问题描述】:

我有一个对记录执行搜索的存储过程。

问题是一些来自 UI 的搜索条件可能是空字符串。 因此,当没有指定条件时,LIKE 语句就变得多余了。

如何有效地执行该搜索或 Sql Server?或者,它是否优化了 LIKE('%%') 查询,因为它意味着没有什么可比较的?

存储过程是这样的:

ALTER PROC [FRA].[MCC_SEARCH]
@MCC_Code varchar(4),
@MCC_Desc nvarchar(50),
@Detail nvarchar(50)
AS
BEGIN             
       SELECT
             MCC_Code,
             MCC_Desc,
             CreateDate,
             CreatingUser

       FROM
              FRA.MCC (NOLOCK)
       WHERE
             MCC_Code LIKE ('%' + @MCC_Code + '%')
             AND MCC_Desc LIKE ('%' + @MCC_Desc + '%')
             AND Detail LIKE ('%' + @Detail + '%')
       ORDER BY MCC_Code

END

【问题讨论】:

    标签: sql sql-server search stored-procedures sql-like


    【解决方案1】:

    关于最佳的、使用索引的执行计划 - 不。前缀通配符可防止使用索引,从而导致扫描。

    如果您在搜索词的末尾也没有通配符,那么可以优化该场景 - 我不久前在博客上发表了一些内容:Optimising wildcard prefixed LIKE conditions

    更新
    为了澄清我的观点:
    LIKE 'Something%' - 能够使用索引
    LIKE '%Something' - 无法使用开箱即用的索引。但是您可以通过遵循我链接到的“反向技术”来优化它以允许它使用索引。
    LIKE '%Something%' - 不能使用索引。您无法针对 LIKE 进行优化。

    【讨论】:

    • @Richard - 不,我的意思是“最后”。即 LIKE '%Something' - 由于该条件的末尾没有通配符,因此可以根据我的博客对其进行优化 - 基本上,将列值反转为计算列,然后反转最终具有% 最后,因此可以使用索引。
    • @Richard - 你在谈论一个不同的场景 - 我特别是在谈论当你想找到 end 与给定字符串(LIKE '%Something ') 它不会使用索引(除非您遵循我在博客中提到的方法)。您正在谈论查找以给定字符串(LIKE 'Something%')开始的项目,这当然可以在没有任何 REVERSE 的情况下用于索引。
    • @Richard - 是的,我知道 - 我将其添加为次要点解决了 OP 询问的特定问题,因为我觉得它可能会为那些现在和将来阅读此 Q。简而言之,只是想强调“%Something”可以优化(因为不是每个人都知道这一点),“Something%”也可以......而“%Something%”不能用 LIKE 优化。使用完整参考的链接,这里没有太多细节,因为它不是对特定 Q 的直接回答。
    【解决方案2】:

    简短的回答是 - 长答案是 - 绝对不是

    它是否优化了 LIKE('%%') 查询,因为它意味着没有什么可比较的?

    该陈述不正确,因为有 东西可供比较。以下是等价的

    WHERE column LIKE '%%'
    WHERE column IS NOT NULL
    

    IS NOT NULL 需要进行表扫描,除非列中的非空值非常少且索引良好。

    编辑

    有关 SQL Server 中动态搜索过程的资源:
    您只需必须阅读 Erland Sommarskog,SQL Server MVP http://www.sommarskog.se/dyn-search.html 撰写的这篇文章(选择您的版本,或同时阅读)

    否则,如果您需要在 CONTAINS 样式搜索中获得良好的性能,请考虑使用 SQL Server 全文引擎。

    【讨论】:

    【解决方案3】:

    如果您使用 LIKE 分句,并指定通配符 (%) 作为搜索字符串的前缀,SQL Server(以及我猜的所有其他 DBMS'es)将无法使用可能存在的索引列。

    如果您使用空的搜索参数,我不知道它是否会优化查询...如果您查看执行计划,也许您的问题可能会得到回答?

    编辑:我刚刚检查了这个,以及这个语句的执行计划:

    select * from mytable
    

    和这个语句的执行计划完全一样:

    select * from mytable where description like '%'
    

    两个 SQL 语句都只是使用聚集索引扫描。

    【讨论】:

    • 在这种情况下为真,但使用LIKE 子句防止优化器使用其他索引。如果您执行select <indexed column>select <indexed column> where ...%,您将获得不同的执行计划。
    • 显然,因为 select from 总是会导致索引扫描,因为索引被完全覆盖了。
    • 你(或我)没有抓住重点。阅读您的答案,OP 可能会得出结论,实际上可能没有性能损失。想象一下,您的查询只需返回 one indexed 列。在此查询中添加另一列上的 where %% 子句将产生性能开销。
    • 你说的确实是对的。但是,在提问者提出的实际情况中,我认为这很明显,因为他选择了他的 where 子句中的列,并且我认为将始终使用相同的索引,无论他是否使用一个 where %% 子句,或者不是。 (实际上,我们不知道 topicstarter 是否在 detail 列上有索引,因为这确实可能是会影响执行计划的列)
    猜你喜欢
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 2014-11-04
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多