Mar*_*röm 12 sql-server ola-hallengren index-maintenance sql-server-2017
数据库 SQL Server 2017 Enterprise CU16 14.0.3076.1
我们最近尝试从默认的 Index Rebuild 维护作业切换到 Ola Hallengren IndexOptimize
。默认的索引重建作业已经运行了几个月没有任何问题,并且查询和更新的执行时间在可接受的范围内。在IndexOptimize
数据库上运行后:
EXECUTE dbo.IndexOptimize
@Databases = 'USER_DATABASES',
@FragmentationLow = NULL,
@FragmentationMedium = 'INDEX_REORGANIZE,INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationHigh = 'INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationLevel1 = 5,
@FragmentationLevel2 = 30,
@UpdateStatistics = 'ALL',
@OnlyModifiedStatistics = 'Y'
Run Code Online (Sandbox Code Playgroud)
性能极度下降。之前花费 100 毫秒的更新语句在之后IndexOptimize
花费了 78.000毫秒(使用相同的计划),并且查询的性能也差了几个数量级。
由于这仍然是一个测试数据库(我们正在从 Oracle 迁移生产系统),我们恢复到备份并禁用IndexOptimize
,一切恢复正常。
但是,我们想了解什么IndexOptimize
与Index Rebuild
可能导致这种极端性能下降的“正常”不同,以确保我们在投入生产后避免这种情况。任何关于寻找什么的建议将不胜感激。
更新语句缓慢时的执行计划。即
IndexOptimize 之后的
实际执行计划(即将推出)
我一直无法发现差异。
快速时为同一个查询做
计划 实际执行计划
Joh*_*ner 11
我怀疑您在两种维护方法之间定义了不同的采样率。我相信 Ola 的脚本使用默认采样,除非您指定@StatisticsSample
参数,这看起来不像您目前正在做的那样。
此时,这是推测,但您可以通过在数据库中运行以下查询来查看当前对统计数据使用的采样率:
SELECT OBJECT_SCHEMA_NAME(st.object_id) + '.' + OBJECT_NAME(st.object_id) AS TableName
, col.name AS ColumnName
, st.name AS StatsName
, sp.last_updated
, sp.rows_sampled
, sp.rows
, (1.0*sp.rows_sampled)/(1.0*sp.rows) AS sample_pct
FROM sys.stats st
INNER JOIN sys.stats_columns st_col
ON st.object_id = st_col.object_id
AND st.stats_id = st_col.stats_id
INNER JOIN sys.columns col
ON st_col.object_id = col.object_id
AND st_col.column_id = col.column_id
CROSS APPLY sys.dm_db_stats_properties (st.object_id, st.stats_id) sp
ORDER BY 1, 2
Run Code Online (Sandbox Code Playgroud)
如果您看到这是 1s(例如 100%),那么这可能是您的问题。也许再次尝试 Ola 的脚本,包括@StatisticsSample
带有此查询返回的百分比的参数,看看是否能解决您的问题?
作为该理论的额外支持证据,执行计划 XML 显示慢查询的采样率有很大不同(2.18233 %):
SELECT OBJECT_SCHEMA_NAME(st.object_id) + '.' + OBJECT_NAME(st.object_id) AS TableName
, col.name AS ColumnName
, st.name AS StatsName
, sp.last_updated
, sp.rows_sampled
, sp.rows
, (1.0*sp.rows_sampled)/(1.0*sp.rows) AS sample_pct
FROM sys.stats st
INNER JOIN sys.stats_columns st_col
ON st.object_id = st_col.object_id
AND st.stats_id = st_col.stats_id
INNER JOIN sys.columns col
ON st_col.object_id = col.object_id
AND st_col.column_id = col.column_id
CROSS APPLY sys.dm_db_stats_properties (st.object_id, st.stats_id) sp
ORDER BY 1, 2
Run Code Online (Sandbox Code Playgroud)
与快速查询 (100%) 对比:
<StatisticsInfo LastUpdate="2019-08-25T23:01:05.52" ModificationCount="555"
SamplingPercent="100" Statistics="[INDX_UPP_4]" Table="[UPPDRAG]"
Schema="[SVALA]" Database="[ulek-sva]" />
Run Code Online (Sandbox Code Playgroud)
约翰的答案是正确的解决方案,这只是关于执行计划的哪些部分发生变化的补充,以及如何轻松发现与Sentry One Plan explorer差异的示例
在 IndexOptimize 之前花费 100 毫秒的更新语句在之后花费了 78.000 毫秒(使用相同的计划)
查看性能下降时的所有查询计划时,您可以轻松发现差异。
性能下降
两次计数超过 35 秒的 CPU 时间和经过时间
预期表现
好多了
此更新查询的主要降级是两次:
UPDATE SVALA.INGÅENDEANALYS
SET
UPPDRAGAVSLUTAT = @NEW$AVSLUTAT
WHERE INGÅENDEANALYS.ID IN
(
SELECT IA.ID
FROM
SVALA.INGÅENDEANALYS AS IA
JOIN SVALA.INGÅENDEANALYSX AS IAX
ON IAX.INGÅENDEANALYS = IA.ID
JOIN SVALA.ANALYSMATERIAL AS AM
ON AM.ID = IA.ANALYSMATERIALID
JOIN SVALA.ANALYSMATERIALX AS AMX
ON AMX.ANALYSMATERIAL = AM.ID
JOIN SVALA.INSÄNTMATERIAL AS IM
ON IM.ID = AM.INSÄNTMATERIALID
JOIN SVALA.INSÄNTMATERIALX AS IMX
ON IMX.INSÄNTMATERIAL = IM.ID
WHERE IM.UPPDRAGSID = SVALA.PKGSVALA$STRIPVERSION(@NEW$ID)
)
Run Code Online (Sandbox Code Playgroud)
此查询的执行计划性能下降
当性能下降时,此更新查询的估计查询计划有非常高的估计:
虽然在现实中(实际的执行计划)它仍然需要工作,只是不是估计显示的疯狂数量。
对性能影响最大的是下面的两次扫描和哈希匹配连接:
对性能下降的实际扫描 #1
对性能下降的实际扫描 #2
具有预期性能的此查询的执行计划
当您将其与具有正常预期性能的查询计划的估计(或实际值)进行比较时,很容易发现差异。
此外,前两个表访问甚至没有发生:
您不会在散列连接上看到这种消除,因为构建(顶部)输入首先插入到散列表中。然后在这个哈希表中探测零值,返回零值。
归档时间: |
|
查看次数: |
977 次 |
最近记录: |