回答

收藏

SQL Server函数间歇性性能问题

技术问答 技术问答 174 人阅读 | 0 人回复 | 2023-09-14

我们的数据库中有一个函数,该函数搜索两个大表以查看是否存在值。这是一个相当大的查询,但已对其进行了优化以使用索引,并且通常运行速度非常快。
- \6 Q+ C& \' v& m; j在过去的2周中,此功能有3次决定进入麻烦境地,并且运行极其缓慢,这会导致死锁和性能下降。即使在少于高峰使用时间的情况下,也会发生这种情况。
; \6 K$ n( }9 T$ Z在SQL Server中使用“更改功能”重建功能似乎可以解决此问题。完成后,服务器使用率将恢复正常,一切正常。( H- G6 P% R+ M+ z
这使我们认为功能查询计划已经重建,并考虑了正确的索引,但是我们不知道为什么SQL Server突然决定将查询计划更改为更差的计划。3 N  ]$ t1 Q/ J& Y1 F
有谁知道可能导致这种行为的原因,或者如何测试或预防这种行为?我们正在运行SQL Server 2008 Enterprise。7 _9 ]. e) w% r6 X2 {5 r; }
                1 V' c/ R' J1 y) ?: H5 M
解决方案:" s# D" |4 a/ }& a
               
+ [0 g  |+ a- L. M  ~% M
5 |2 Z- P" u1 P" T% g. X- j# q4 E3 l5 l% K
                您描述的行为通常是由于缓存了错误的查询计划和/或过时的统计信息造成的。/ _- U4 R6 B+ s% V  u
当您在WHERE子句中有大量参数时,特别是一长串形式的参数时,通常会发生这种情况:) x/ E; m( r) z# h
(@parameter1 is NULL OR TableColumn1 = @parameter1)
; Y4 \3 I% r5 Q, E1 g' Y假设缓存的查询计划已过期,并且使用一组不具有代表性的参数来调用proc。然后为该数据配置文件缓存该计划。但是,如果proc在一组非常不同的参数中更常见,则该计划可能不合适。这通常被称为“参数嗅探”。
  ^5 m* |  ^5 `6 i/ C有许多方法可以缓解和消除此问题,但是它们可能涉及折衷,并且取决于您的SQL Server版本。看看OPTIMIZE
7 U. B; b: h6 z! FFOR和OPTIMIZE FOR: z/ R6 O2 y; _* r
UNKNOWN。如果不经常调用proc(如果这很重要),但是必须尽可能快地运行,您可以将其标记为OPTION(RECOMPILE),以在每次调用时强制重新编译,但不要对经常调用的proc进行此操作,否则请不要进行调查。  j9 ?4 Z, D4 c( E
[注意:请注意您的SQL Server 2008框具有哪个Service
6 [! _! @1 c- {; V7 s0 G/ vPack和累积更新(CU),因为在某些版本中,重新编译和参数嗅探逻辑的工作方式有所不同]
8 G; v, {) l0 q$ b, Y' y运行此查询(来自Glenn Berry)以确定统计信息的状态:1 ?. H/ ^- d. a0 W/ u3 z. Z
-- When were Statistics last updated on all indexes?% V! a) o. |, f- P" S: l
SELECT o.name, i.name AS [Index Name],  ( P% x1 Y1 M2 Y" z% p# f; _
      STATS_DATE(i.[object_id], i.index_id) AS [Statistics Date], 3 q- V/ }2 Y* y# J; f
      s.auto_created, s.no_recompute, s.user_created, st.row_count' D) D1 W- O, R9 }) {1 S9 q
FROM sys.objects AS o WITH (NOLOCK)
$ m! ?$ R' G0 x0 \; \/ [INNER JOIN sys.indexes AS i WITH (NOLOCK)% G. C( }4 z3 |0 Q8 \, I# J& S* q
ON o.[object_id] = i.[object_id]
! }  j( u1 K- f; NINNER JOIN sys.stats AS s WITH (NOLOCK)/ m% j! h% [# t! s
ON i.[object_id] = s.[object_id] ' Q; t$ @  E/ q9 l* W7 O
AND i.index_id = s.stats_id
, F) m3 H# b3 A! u3 U/ cINNER JOIN sys.dm_db_partition_stats AS st WITH (NOLOCK)( a4 |+ P6 S4 A4 O7 U/ P: N- V
ON o.[object_id] = st.[object_id]  }  |& U( g$ m
AND i.[index_id] = st.[index_id]7 j: o1 C; N6 J/ `& B9 y
WHERE o.[type] = 'U'
) u; O5 F2 R% T8 G8 g$ V2 N$ @ORDER BY STATS_DATE(i.[object_id], i.index_id) ASC OPTION (RECOMPILE);
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则