2011-01-29 45 views
0

我们的数据库中有一个函数,用于搜索两个大表来查看是否存在值。这是一个相当大的查询,但它被优化为使用索引,并且运行速度非常快。SQL Server函数间歇性性能问题

在过去的两周里,这个功能决定了三次失灵,运行速度非常慢,从而导致死锁和性能不佳。即使在使用量不足的情况下也会发生这种情况。

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

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

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

+1

我们可能需要更多信息。它是什么类型的函数(标量,表值或内联)?它运行的表格有哪些结构?哪些索引可用,以及您期望它使用哪些索引?它开始表现不好时究竟做了什么? – 2011-01-29 00:31:28

回答

5

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

当你在WHERE子句,尤其是那些形式的一长串大量的参数,它通常发生:

(@parameter1 is NULL OR TableColumn1 = @parameter1) 

说,缓存的查询计划的到期,和proc被称为一个非代表性的一组参数。然后该计划被缓存用于该数据配置文件。但是,如果程序更常用于一组非常不同的参数,则该计划可能不合适。这通常被称为“参数嗅探”。

有一些方法可以减轻和消除此问题,但它们可能涉及权衡并取决于您的SQL Server版本。看看OPTIMIZE FOROPTIMIZE FOR UNKNOWN。如果(如果)这个过程不经常被调用,但必须尽可能快地运行,你可以将它标记为OPTION(RECOMPILE),每次调用它时强制重新编译,但不要为频繁调用的过程执行此操作,或者在没有调查的情况下。

[注:知道哪些Service pack and Cumulative Update (CU)您的SQL Server 2008框有,因为重新编译和参数嗅探逻辑在一些版本的工作方式不同]

运行此查询(由格伦·贝瑞),以确定国家统计:

-- 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); 
+0

我同意这听起来像参数嗅探。过时的统计数据似乎不符合事实,但如果统计数据不好,那么通过“Alter Function”重新编译计划不能解决问题。 – 2011-01-29 00:53:36