可以使用ISNULL在WHERE语句引起的问题,使用索引?
-
21-09-2019 - |
题
我有如下所示的查询:
SELECT t1.v3, t2.v2
FROM t1
INNER JOIN t2
ON t1.v1 = t2.v1
WHERE ISNULL(t1.DeleteFlag,'N') = 'N'
我已经制定的指标,我认为应该导致有索引查找的= 'N'
一部分,而是我看到一个非常昂贵的索引扫描。难道该指数是搞乱正确使用索引?它甚至有意义有一个列的索引只会有几个可能的值(如DeleteFlag
会)?
解决方案
是,任何功能的WHERE子句将有可能赚了指数窝囊调用。尝试重写它,使得索引可用于:
SELECT t1.v3, t2.v2
FROM t1
INNER JOIN t2
ON t1.v1 = t2.v1
WHERE NOT t1.DeleteFlag = 'Y'
的索引有意义如果从查询期望的结果的数量比行表中的总数小得多。
其他提示
1)是否使用ISNULL的转寻求成扫描?是。在一般应用函数到列使表达非SARG-能够(未搜索)。为了使指数被认为是为寻求操作中的发动机需要知道所追求的价值,作为原始二进制值。只要你申请一个函数列你问到搜索的结果的功能,所以它必须评估在每一行的功能,看看结果恰好满足条件。
2)是否有意义有上的列的索引与非常低的选择性(2-3值)?是的,但从来没有作为一个独立的索引表达式。该指数转折点将使在低选择性列的独立指标只是浪费空间。但是,像位和标志非常低的选择性列在索引最左边的键,与多个按键组成非常有用。在你的情况,考虑到被删除标志,这将是有意义的是聚集索引的第一个关键,因为预期的每一个的查询将指定“请将isDeleted”状态。
我也想补充一点,你应该没有空值在“删除”标志。
标记Byers公司的回答是不行的,它是由于SQL Server将空值的非常微妙的方式。在WHERE表述“t1.DeleteFlag =‘Y’”如果t1.DeleteFlag是NULL,则表达式返回NULL。这样做NOT(NULL)也返回NULL和失败WHERE条件。尝试这样做测试:
DECLARE @myvar VARCHAR(1)
SET @myvar = NULL
SELECT 'OK' WHERE ISNULL(@myvar, 'N') = 'N' -- Baseline statement. Returns OK
SELECT 'OK' WHERE NOT (@myvar = 'Y') -- Equivalent to answer above. Fails
SELECT 'OK' WHERE @myvar = 'N' OR @myvar IS NULL -- This is another way to do it. Also returns OK
在第二选择语句不返回任何行,以便因此不等同于基线语句,因此不工作。第三个语句是另一种方式编写这个查询哪一个,工作,和二,仍确保了该领域的索引可以被使用。
所以,这里是一个正确的答案的问题:
SELECT t1.v3, t2.v2
FROM t1
INNER JOIN t2
ON t1.v1 = t2.v1
WHERE (t1.DeleteFlag = 'N' OR t1.DeleteFlag IS NULL)
此的替代,这可能会产生更好的标称性能的结果,将定义DeleteFlag字段为“NOT NULL”,并给它的'一个DEFAULT(空字符串)。然后,该查询可以被简单地没有空值的忧虑写成:
SELECT t1.v3, t2.v2
FROM t1
INNER JOIN t2
ON t1.v1 = t2.v1
WHERE t1.DeleteFlag = 'N'