为什么我的查询不是sargable

时间:2013-10-29 08:03:41

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

我有一个非常奇怪的问题。

我在SQL Server 2008 R2中运行了这样的查询:

SELECT TOP (20) *
FROM MyTable
WHERE a = 0
    AND b = 0
    AND c = 0

在MyTable上使用我的索引

但这个没有:

SELECT TOP (20) *
FROM MyTable
WHERE a = 0
    OR b = 0
    OR c = 0

我想在我的程序中执行第二个查询。如何更改第二个查询以使用索引?

索引是:

CREATE NONCLUSTERED INDEX [MyIndex] ON [dbo].[MyTable] (
[a] ASC,
[b] ASC,
[c] ASC
)
WITH (
        PAD_INDEX = OFF,
        STATISTICS_NORECOMPUTE = OFF,
        SORT_IN_TEMPDB = OFF,
        IGNORE_DUP_KEY = OFF,
        DROP_EXISTING = OFF,
        ONLINE = OFF,
        ALLOW_ROW_LOCKS = ON,
        ALLOW_PAGE_LOCKS = ON
        ) ON [PRIMARY]

3 个答案:

答案 0 :(得分:5)

对于条件之间or的查询,您不能使用该索引。试想一下:任何一个值都可以匹配,因此索引匹配不能保证没有其他记录符合该条件。

这就像运行单独的搜索然后将它们匹配在一起一样。

答案 1 :(得分:0)

为了使用Index,SQL-Server会检查很多东西

1)如果过滤器是SARG。

2)指数使用似然比(唯一记录数:总记录数)

3)没有要获取的记录(如果记录较少,可以使用索引或者表扫描。因为sql-server发现扫描整个表比查找和使用索引更容易记录数量巨大。)

4)在您的查询中,因为您正在使用OR,所以记录数量增加,在哪种情况下,sql-server发现扫描整个表比查找/更容易使用索引。如果是AND,则使用索引的可能性会增加。

答案 2 :(得分:0)

其他回答者说的是真的。但是,您可以使用技巧:

SELECT TOP (20) *
(
select TOP(20) *
FROM MyTable
WHERE a = 0

union

SELECT TOP(20) *
FROM MyTable
WHERE b = 0

union

SELECT TOP(20) *
FROM MyTable
WHERE c = 0
)

每个子查询都可以使用单独的索引。所以,现在您只需要3个独立的索引(前导列分别为a,b和c),您就可以了。