具有like和where模式的列的索引?

时间:2013-04-18 13:34:18

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

我得出这样的结论,就像在下面的情况下确实寻找/扫描但我没有得到 为什么它在第一种情况下扫描并在第二种情况下寻找。我理解第三种情况。

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

如果我在contactname上建立一个索引,该索引具有以下样本数据,那将是怎样的 索引树..就像我们为数字构建它将比较小于和大于 将在下面的例子中遍历索引树的遍历方式。

c.contactname

mark
anna
krishna
nadejda
allen
bob
cab

3 个答案:

答案 0 :(得分:4)

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

树可能看起来像这样:

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

因此,搜索a%可以完成,因为索引将知道每个分支的去向。例如,C> A,所以走吧。搜索%a无法有效实现。索引必须读取所有数据,以确定每个节点是否以A结尾。必须读取所有数据意味着使用索引只是浪费了开销。

答案 1 :(得分:4)

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

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

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

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

答案 2 :(得分:4)

好的,在你的字符串列上创建索引时,为了解决这个问题。它将以第一个字母存储它们,以便您的数据存储如下。

allen
anna
bob
cab
krishna
mark
nadejda

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

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