我有一堆表,我正在加入搜索查询。此查询允许多个可选参数。但它正在搜索的主表(T_AS400_BLRPIN00
)有超过200万行。
当我运行执行计划时,大部分时间都花费在非聚集索引扫描上。
表格(T_AS400_BLRPIN00)有38列,我不会在这里列出所有列(除非你认为有必要),但有些关键字段是:
INSPASER (int, null) -- Part of the old key
INSPIND (varchar(1), null) -- The other part of the old key
T_AS400_BLRPIN00_ID (PK, int, not null) -- The new key
使用的索引如下所示:
CREATE NONCLUSTERED INDEX [IX01_T_AS400_BLRPIN00]
ON [dbo].[T_AS400_BLRPIN00]
(
[INSPASER] ASC,
[INSPIND] ASC
)
我的存储过程/查询会像这样搜索表:
FROM
dbo.T_AS400_BLRPIN00 AS Insp
LEFT JOIN
dbo.T_AS400_BLRPEQP00 AS Eqp ON Insp.T_AS400_BLRPEQP00_ID = Eqp.T_AS400_BLRPEQP00_ID
WHERE
(@pint_INSPASER=0 OR Insp.INSPASER = @pint_INSPASER)
AND
(ISNULL(INSPIND,'') like '%' + @pstr_INSPIND + '%')
我不喜欢用varchar
搜索这么大的桌子,但是现在我们需要这种能力。有时候@pstr_INSPIND
是一个空字符串(''),因为它们没有按字母搜索,有时它只是一个字符()。
执行计划显示索引扫描(非聚集)占63%,然后密钥查找的嵌套循环(内部联接)占36%。
我有更好的方法来设计这个吗?
答案 0 :(得分:1)
尝试更改此
WHERE
(@pint_INSPASER=0 OR Insp.INSPASER = @pint_INSPASER)
AND
(ISNULL(INSPIND,'') like '%' + @pstr_INSPIND + '%')
到这个
WHERE
(@pint_INSPASER=0 OR Insp.INSPASER = @pint_INSPASER)
AND
(INSPIND = @pstr_INSPIND or INSPIND is NULL)
答案 1 :(得分:0)
执行like '%abc%'
是致命的 - 你根本就没有使用索引。
因此,您可以通过完全从复合索引中删除它来获得更好的性能。
此外,如果可能,请尝试减少搜索,以便您执行like 'abc%'
- 实际上可以使用索引。另外,为什么您在%
列上使用varchar(1)
?
答案 2 :(得分:0)
“喜欢”很糟糕。此外,该变量(@pstr_INSPIND)中的内容是什么? Parameter sniffing?
您的统计数据是什么样的?返回估计的vs实际行数?
不确定如何填充@pstr_INSPIND,但您可能对sqlinjection开放。