SQL Server功能间歇性性能问题

Bri*_*can 0 sql sql-server sql-function sql-server-2008

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

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

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

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

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

Mit*_*eat 5

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

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

(@parameter1 is NULL OR TableColumn1 = @parameter1)
Run Code Online (Sandbox Code Playgroud)

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

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

[注意:请注意您的SQL Server 2008框具有哪些Service Pack和累积更新(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); 
Run Code Online (Sandbox Code Playgroud)