Sql server 使用联合/或的TSQL存储过程性能问题
我有一个静态表,我创建并构建索引,然后在该表上创建一个要运行的存储过程。我的问题很奇怪,我会尽力解释的 我运行相同的脚本来创建和执行194个数据库…其中绝大多数运行得非常快…但是在少数数据库上,它们运行得非常慢Sql server 使用联合/或的TSQL存储过程性能问题,sql-server,performance,stored-procedures,indexing,query-optimization,Sql Server,Performance,Stored Procedures,Indexing,Query Optimization,我有一个静态表,我创建并构建索引,然后在该表上创建一个要运行的存储过程。我的问题很奇怪,我会尽力解释的 我运行相同的脚本来创建和执行194个数据库…其中绝大多数运行得非常快…但是在少数数据库上,它们运行得非常慢 CREATE PROC dbo.DC_GetPotentialDuplicates @ID int, @FirstName varchar(30), @LastName varchar(30), @PostalCode var
CREATE PROC dbo.DC_GetPotentialDuplicates
@ID int,
@FirstName varchar(30),
@LastName varchar(30),
@PostalCode varchar(10),
@YearBorn varchar(4)
AS
SELECT *
FROM DC_DuplicateMatch
WHERE (ID > @ID) AND
(
(LastName = @LastName AND FirstName = @FirstName) OR
(LastName = @LastName AND PostalCode = @PostalCode) OR
(LastName = @LastName AND YearBorn = @YearBorn) OR
(FirstName = @FirstName AND PostalCode = @PostalCode) OR
(FirstName = @FirstName AND YearBorn = @YearBorn) OR
(PostalCode = @PostalCode AND YearBorn = @YearBorn)
)
OPTION (RECOMPILE)
GO
此过程在较大的表上始终运行得更快…较小的表“偶尔”运行得更慢。速度范围从4000条记录/秒“快”到70条记录/秒“慢”
问题是,如果我在某个点将空白填充记录添加到目标表中,而不进行任何其他更改,则速度将从70向上增加,接近4000标记。这就好像查询计划没有根据表中的记录数正确构建一样
为了避免添加空白记录以提高速度的麻烦,我重写了存储过程,使用联合而不是OR(生成相同的输出结果)
现在,这个存储过程在所有大型表上运行的速度都一样快……并且在大约1/2较小的有问题的表上提高了速度……但在其余的表上只给了我一点小小的改进。同样,如果我在较小的表上增加空白记录的记录数,性能也会提高
在运行了数据库引擎调谐器和性能监视器之后,无论是强制计划还是我尝试的任何优化,命中较小问题表的进程都会导致表扫描
有什么建议可以帮助我解决这个问题吗
~~~~~已更新~~~~我已经大大缩小了问题的范围,这与一个没有缺失的索引有关 我刚刚发现,当我对联合进行重新排序时,列表中的最后一个联合无法使用索引,即使它在那里** 在上面的代码示例中,我确实交换了第一个和最后一个联合,现在存储的进程对LastName和firtname进行了表扫描,分析器抱怨索引丢失。
~~~~~~~~~
我已创建了一个新问题,该问题可以更好地定义问题,并包含位于此处的解决方案
您可以计数重复项,而不是检查每个排列:
SELECT *
FROM DC_DuplicateMatch
WHERE (ID > @ID) AND
(
CASE [LastName] WHEN @LastName THEN 1 ELSE 0 END +
CASE [FirstName] WHEN @FirstName THEN 1 ELSE 0 END +
CASE [PostalCode] WHEN @PostalCode THEN 1 ELSE 0 END +
CASE [YearBorn] WHEN @YearBorn THEN 1 ELSE 0 END
) >= 2
您可以计数重复项,而不是检查每个排列:
SELECT *
FROM DC_DuplicateMatch
WHERE (ID > @ID) AND
(
CASE [LastName] WHEN @LastName THEN 1 ELSE 0 END +
CASE [FirstName] WHEN @FirstName THEN 1 ELSE 0 END +
CASE [PostalCode] WHEN @PostalCode THEN 1 ELSE 0 END +
CASE [YearBorn] WHEN @YearBorn THEN 1 ELSE 0 END
) >= 2
您是否定期更新小表的统计数据?如果您不需要筛选重复的行,Als、o UNION ALL将运行得更快。表上有哪些索引?所有表都完全相同吗?将varchar隐式转换为nvarchar将导致索引扫描比seek更频繁。所有表都与我使用的相同.sql文件完全相同。我从头开始重新创建表,填充它们,然后创建索引。我还在末尾添加了updatestatistics调用,但没有效果。很可能是由于表中的数据不同,查询计划发生了更改。发布计划的两种变体。是否定期更新小表的统计信息?如果您不需要筛选重复的行,Als、o UNION ALL将运行得更快。表上有哪些索引?所有表都完全相同吗?将varchar隐式转换为nvarchar将导致索引扫描比seek更频繁。所有表都与我使用的相同.sql文件完全相同。我从头开始重新创建表,填充它们,然后创建索引。我还在末尾添加了updatestatistics调用,但没有效果。很可能是由于表中的数据不同,查询计划发生了更改。张贴计划的两个变体。