【问题标题】:% in the beginning of like clause% 在 like 子句的开头
【发布时间】:2009-10-09 01:23:52
【问题描述】:

听说由于性能原因不建议在SQL Server的LIKE子句开头使用%,为什么会这样?

有关此问题的更多详细信息将有助于我了解此问题的影响。

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    LIKE 子句开头的% 意味着索引完全没用。如果有静态文本将模式锚定到% 前面,那么至少可以从索引中获得潜在的效用。

    【讨论】:

      【解决方案2】:

      %foo 基本上说“所有以 'foo' 结尾的字符串”。为了过滤掉这些,SQL 服务器必须扫描所有表(在最坏的情况下)并检查每个字符串。这就是它如此昂贵的原因。

      【讨论】:

        【解决方案3】:

        为什么 LIKE '%...' 不好?您不能使用任何索引,必须扫描整个表。

        这是一个很好的例子:

        去电话簿找我 匹配 '%ch' 的名称。那将 需要一段时间,因为你不是 能够使用聚集索引,而且必须扫描整本书!

        给定数据'abcdefg'

        WHERE Column1 LIKE '%cde%'  --can't use an index
        
        WHERE Column1 LIKE 'abc%' --can use and index
        
        WHERE Column1 Like '%defg' --can't use an index, but see note below
        

        注意:如果您有需要 '%defg' 的重要查询,则可以在 REVERSE() 列中使用持久计算列,然后对其进行索引。然后您可以查询:

        WHERE Column1Reverse Like REVERSE('defg')+'%' --can use the persistent computed column's index
        

        要添加一个持久计算列(反转字符串)并在其上建立索引,请使用以下代码:

        ALTER TABLE YourTable ADD ReversedYourString  AS REVERSE(YourString) PERSISTED 
        
        CREATE NONCLUSTERED INDEX IX_YourTable_ReversedYourString 
        ON YourTable (ReversedYourString) 
        

        【讨论】:

          【解决方案4】:

          将它放在任何地方都会增加性能消耗,因为文本字段的内容没有索引。

          在开始时,它必须在最坏的情况下搜索到文本字段的末尾。

          【讨论】:

          • 如果字段的开头是固定的,一些(可能是大多数)数据库引擎将使用索引。就像你在“Abc%”上搜索一样,它可以使用索引找到第一个“Abc”,然后从那里依次搜索。但是当字符串以“%”开头时……查看所有其他答案。
          【解决方案5】:

          如果子句开头有 %,则查询引擎无法生成使用索引但必须进行表扫描的查询计划。

          【讨论】:

            【解决方案6】:

            很多人已经解释了为什么 col1 like '%...' 不好。

            如果您经常遇到这种情况,这里有一个潜在的解决方法:

            • 创建另一列,比如 col2
            • 在 col1 的插入/更新时编写一个触发器,用 col1 “向后”填充 col2
            • 在 col2 上创建索引
            • 如果您的应用程序必须像 '%...' 那样搜索 col1,请改为像 '...%' 那样搜索 col2(或者甚至 substr(col1, etc.) = '...' [请原谅我的 oracle方言]

            我们用它来搜索 VIN(车辆识别号码)或社会安全号码的最后一位,效果很好!性能提升真的很棒

            【讨论】:

            • 忘记使用触发器,使用计算列效率更高。你只需要 REVERSE() 原始值,你可以使用我答案中的示例代码搜索它。
            • Computed Columns 似乎是特定于 SQLServer 的,它当然是一个不错且优雅的解决方案。如前所述,我更像是 Oracle 人。
            【解决方案7】:

            全表扫描

            DBA 最害怕什么 ;)

            由于无法通过索引加快搜索速度,服务器必须遍历表中的每条记录(= 表扫描)并检查记录是否与 LIKE 表达式匹配。

            这对于小型表可能不是问题,但对于具有大量行的大型表来说肯定是问题,因为所有记录都必须从磁盘中获取。

            这与索引扫描相反,其中搜索条件允许服务器使用索引将搜索限制为(理想情况下)一小部分记录。

            【讨论】:

              猜你喜欢
              • 2011-03-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多