关于指数的问题

时间:2011-05-31 10:12:23

标签: sql-server sql-server-2005 sql-server-2008 indexing

我有以下查询:

            SELECT 
                  M.Col7,   
                  M.Col8,   
                  M.Col9,   
                      M.Col10   

                FROM    [MyTable] M                    

        WHERE   M.Col1 = COALESCE(@Col1, M.Col1)              
                AND M.Col2 = COALESCE(@Col2, M.Col2)              
                AND M.Col3 = COALESCE(@Col3,              
                                                M.Col3)              
                AND M.Col4 = COALESCE(@Col4,              
                                                 M.Col4)              
                AND M.Col5 = COALESCE(@Col5,              
                                                    M.Col5)              
                AND M.Col6 LIKE COALESCE(@Col6, M.Col6) +'%'

我在col7,8,9,10列上有一个组合的非聚集索引。如果我删除where子句,查询运行正常。但是一旦我把where子句放入查询就需要很长时间才能执行。我的桌子有200 K行。现在我想把一个非聚集索引放在列中,按照这个顺序Col1,2,3,4,5,6。我是否正确地做到这一点或者什么应该是最好的选择呢?

4 个答案:

答案 0 :(得分:3)

尝试使用覆盖索引

CREATE INDEX IX_foo ON MyTable
   (Col1,Col2,Col3,Col4,Col5,Col6)
   INCLUDE (Col7,Col8,Col9,Col10)

其他想法:

其他:

  • 什么是聚集索引和主键?

编辑,解释WHERE评论

WHERE
    M.Col1 = ISNULL(@Col1, M.Col1)
    AND
    ...

OR

WHERE
    (@Col1 IS NULL OR M.Col1 = @Col1
    AND
    ...

答案 1 :(得分:0)

除了创建覆盖索引外,

CREATE INDEX NC_Col1Col2Col3Col4Col5Col6_I_Col7Col8Col9Col10
   ON MyTable(Col1, Col2, Col3, Col4, Col5, Col6)   
      INCLUDE (Col7, Col8, Col9, Col10)

我会使用ISNULL()而不是COALESCE()进行基准测试,并将WHERE子句置于SARG格式中,以便可以使用索引,例如

WHERE  (@Col1 IS NULL OR M.Col1 = @Col1)
       AND   -- etc...

答案 2 :(得分:0)

@gbn这样的查询覆盖索引可能是最好的主意。

另一方面,覆盖很多列的索引并不是一个好主意......

我会在WHERE子句中的大多数选择性列上尝试(如果可能)群集索引

这个索引的最小化大小并可以直接访问所有其他列 - 这可能足以加快查询速度。

答案 3 :(得分:0)

洛矶,

到目前为止给出的所有答案都会有所帮助。但我不得不说,我认为问题比缺失指数更深。

首先,纯粹的猜测,但你表中已经有200k行的事实告诉我,有很多插件发生,即使没有,运行超过200K行的功能慢一点,减慢你得到的行数。

我建议在你的where子句中使用CASE语句。这将消除它扫描的每一行的FUNCTION调用多次次。此外,它还将为SQL Server生成更好的查询执行计划,或者更确切地说,允许SQL Server根据我的经验选择更优化的计划

所以这是修改过的查询:

SELECT M.Col7, M.Col8, M.Col9, M.Col10   
FROM [MyTable] M                    
WHERE M.Col1 = CASE WHEN @Col1 IS NULL THEN M.Col1 ELSE @Col1 END
    AND M.Col2 = CASE WHEN @Col2 IS NULL THEN M.Col2 ELSE @Col2 END           
    AND M.Col3 = CASE WHEN @Col3 IS NULL THEN M.Col3 ELSE @Col3 END             
    AND M.Col4 = CASE WHEN @Col4 IS NULL THEN M.Col4 ELSE @Col4 END              
    AND M.Col5 = CASE WHEN @Col5 IS NULL THEN M.Col5 ELSE @Col5 END              
    AND M.Col6 LIKE CASE WHEN @Col6 IS NULL THEN M.Col6 ELSE @Col6 END +'%'

希望这会有所帮助。然后添加@ gbn的索引(+1)。