0

我们的数据库中有一个函数可以搜索两个大表以查看值是否存在。这是一个相当大的查询,但它已针对使用索引进行了优化,并且通常运行得非常快。

在过去的 2 周内,该函数 3 次决定失控并且运行速度极慢,从而导致死锁和性能不佳。即使在低于峰值使用量的时候也会发生这种情况。

在 SQL Server 中使用“Alter Function”重建函数似乎可以解决这个问题。一旦我们这样做了,服务器使用就会恢复正常,一切正常。

这使我们认为函数查询计划已经重建,并且正在考虑正确的索引,但我们不知道为什么 SQL Server 突然决定将查询计划更改为更糟糕的计划。

有没有人知道什么可能导致这种行为,或者如何测试它,或者防止它?我们正在运行 SQL Server 2008 Enterprise。

4

1 回答 1

5

您所描述的行为通常是由于不正确的缓存查询计划和/或过时的统计信息造成的。

当您在 WHERE 子句中有大量参数时,通常会发生这种情况,尤其是一长串具有以下形式的参数:

(@parameter1 is NULL OR TableColumn1 = @parameter1)

比如说,缓存的查询计划过期了,并且使用一组不具代表性的参数调用 proc。然后为该数据配置文件缓存该计划。但是,如果 proc 更常见的是一组非常不同的参数,则该计划可能不合适。这通常被称为“参数嗅探”。

有一些方法可以缓解和消除此问题,但它们可能需要权衡取舍并取决于您的 SQL Server 版本。看OPTIMIZE FOROPTIMIZE FOR UNKNOWN。如果(这是一个很大的情况)proc 不经常被调用,但必须尽可能快地运行,您可以将其标记为OPTION(RECOMPILE),以在每次调用时强制重新编译,但不要对经常调用的 proc 执行此操作或未经调查。

[注意:请注意您的 SQL Server 2008 机器具有哪个服务包和累积更新 (CU) ,因为重新编译和参数嗅探逻辑在某些版本中的工作方式不同]

运行此查询(来自 Glenn Berry)以确定统计信息的状态:

-- When were Statistics last updated on all indexes?
SELECT o.name, i.name AS [Index Name],  
      STATS_DATE(i.[object_id], i.index_id) AS [Statistics Date], 
      s.auto_created, s.no_recompute, s.user_created, st.row_count
FROM sys.objects AS o WITH (NOLOCK)
INNER JOIN sys.indexes AS i WITH (NOLOCK)
ON o.[object_id] = i.[object_id]
INNER JOIN sys.stats AS s WITH (NOLOCK)
ON i.[object_id] = s.[object_id] 
AND i.index_id = s.stats_id
INNER JOIN sys.dm_db_partition_stats AS st WITH (NOLOCK)
ON o.[object_id] = st.[object_id]
AND i.[index_id] = st.[index_id]
WHERE o.[type] = 'U'
ORDER BY STATS_DATE(i.[object_id], i.index_id) ASC OPTION (RECOMPILE); 
于 2011-01-29T00:31:43.947 回答