【问题标题】:Index on a column with like and where pattern?在具有like 和 where 模式的列上建立索引?
【发布时间】:2013-04-18 13:34:17
【问题描述】:

我得出的结论是,在以下情况下,确实会搜索/扫描,但我没有得到 为什么它在第一种情况下扫描并在第二种情况下搜索。第三种情况我理解了。

SELECT c.contactname FROM Sales.Customers c
WHERE c.contactname LIKE '%a'-- Does a Scan 1st Case

SELECT c.contactname FROM Sales.Customers c
WHERE c.contactname LIKE 'a%'-- Does a Seek 2nd Case

SELECT c.contactname FROM Sales.Customers c
WHERE c.contactname LIKE '%a%'-- Does a Scan

如果我在联系人姓名上建立一个索引,该索引具有以下示例数据,那将如何 索引树..就像我们为数字构建它会比较小于和 在以下情况下将遍历索引树的遍历方式。

c.contactname

mark
anna
krishna
nadejda
allen
bob
cab

【问题讨论】:

    标签: sql sql-server sql-server-2008 sql-server-2008-r2


    【解决方案1】:

    这确实是 SQL Server 的工作方式。你在问为什么。

    想想索引。从功能上讲,您可以将其视为按字母顺序存储contactname——很像字典或电话簿。 (是的,它通常是一个更复杂的数据结构,通常是 B 树,但结果是按顺序排列的项)。

    当您说contactname like 'a%' 时,查询优化器知道它只需要查看以字母“a”开头的条目。索引确切地知道它们在哪里,因此优化器可以使用搜索来找到它们。 SQL Server 为like 实现了这种优化(并非所有数据库都这样做)。

    当您说contactname like '%a' 时,您是在说“找到以'a' 结尾的条目”。这很像通过字典查找所有以“a”结尾的单词。订购没有任何帮助。可能存在以“a”开头并以“a”结尾的条目。可能存在以“z”开头并以“a”结尾的条目。因此,这些类型的表达式需要扫描而不是查找。

    【讨论】:

      【解决方案2】:

      它在第一种情况下进行扫描,原因与第三种情况相同:索引根据字符串开头的数据进行搜索。在模式开头使用通配符,无法智能地搜索索引以查找匹配项。该索引对字符串进行字典(字母)比较,即小于/大于比较。

      这棵树可能看起来像这样:

              /nadejda
          mark
         /    \krishna
      cab
         \    /bob
          anna
              \allen
      

      所以,可以搜索a%,因为索引会知道每个分支的去向。例如,C > A,所以向左走。搜索%a 效率不高。索引必须读取所有数据才能确定每个节点是否以 A 结尾。必须读取所有数据意味着使用索引只是浪费开销。

      【讨论】:

        【解决方案3】:

        好的,当您在字符串列上创建索引时,为您分解这一点。它将按第一个字母存储它们,因此您的数据将像这样存储。

        allen
        anna
        bob
        cab
        krishna
        mark
        nadejda
        

        因此,当您在执行LIKE 'a%' 时,Sql 服务器可以通过查看开头带有“A”的所有内容的顺序来使用索引来减少结果。但是,一旦您将通配符放在末尾 LIKE '%A',您现在已经强制引擎扫描整个表以查找以字母 A 结尾的任何内容。

        当然,这是一个非常简单的解释。

        【讨论】:

        • “通过查看所有以'A'开头的所有内容的顺序。” ...并在找到不以@987654324开头的字母时立即停止@(例如,此示例中的 bob。)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-12
        • 2012-09-17
        • 1970-01-01
        • 2022-01-24
        • 1970-01-01
        相关资源
        最近更新 更多