我有如下所示的查询:

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'
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top