SQL Server功能间歇性性能问题

时间:2011-01-29 00:25:02

标签: sql sql-server sql-server-2008 sql-function

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

在过去的两周内,这个功能已经三次失败,并且运行速度非常慢,导致死机和性能不佳。即使在低于使用峰值的时候也会发生这种情况。

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

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

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

1 个答案:

答案 0 :(得分:5)

您所描述的行为通常是由于错误缓存的查询计划和/或过时的统计信息。

当WHERE子句中有大量参数时,通常会发生这种情况,特别是那些形式为的长列表:

(@parameter1 is NULL OR TableColumn1 = @parameter1)

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

有一些方法可以缓解并消除此问题,但它们可能需要权衡取决于您的SQL Server版本。查看OPTIMIZE FOROPTIMIZE FOR UNKNOWN。 IF(并且它是一个很大的if)proc很少被调用但是必须尽可能快地运行你可以将它标记为OPTION(RECOMPILE),每次调用它时强制重新编译,但是不要经常调用它无需调查即可进行OR。

[注意:请注意您的SQL Server 2008框中有Service pack and Cumulative Update (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);