我有以下查询:
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。我是否正确地做到这一点或者什么应该是最好的选择呢?
答案 0 :(得分:3)
尝试使用覆盖索引
CREATE INDEX IX_foo ON MyTable
(Col1,Col2,Col3,Col4,Col5,Col6)
INCLUDE (Col7,Col8,Col9,Col10)
其他想法:
(ISNULL OR ..)
模式已经过优化(到了一个点,YMMV)
再次查看Why IsNull is twice slow as coalesce (same query)? 其他:
编辑,解释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)。