SQL Server 2008 R2 中的 AUTO_UPDATE_STATISTICS 和 FULLSCAN

CAF*_*FxX 3 sql-server best-practices t-sql sql-server-2008-r2

是否可以强制SQL Server 2008 R2自动FULLSCAN更新统计信息?

如果没有,计划UPDATE STATISTICS WITH FULLSCAN是保持最新统计数据的最佳方式吗?

注意:FULLSCAN当使用非FULLSCAN统计时,需要通过证明次优计划生成来实现。

Mar*_*ith 5

自动更新始终使用根据索引中的行数计算百分比的抽样。

从您的SO 帖子

 Just FYI, the two indexes were PKs of tables having 280M+ and 55M+ rows, respectively.
Run Code Online (Sandbox Code Playgroud)

我想这是 SQL Server 不允许FULLSCAN自动更新的一个很好的例子。计划外读取许多行的影响可能会引起与它解决的一样多的麻烦。

两种选择:

  • 禁用自动更新并安排完整扫描。
  • 轻推/提示/大锤使查询优化器使用首选计划,而不依赖于 100% 准确的统计数据。

John Sansom 试图通过他对您的 SO 帖子的评论来引导您走第二条路,您的回应表明您不热衷于这个想法?

我真的不明白这与实际问题有什么关系......无论如何,请考虑次优计划使用了两个聚集索引扫描,而在最佳计划中它们不存在(由相同索引上的搜索替换)。

如果不能足够频繁地进行全面扫描以保持最新的统计信息并保持良好的执行计划,那么还有其他选择。给定有关问题执行计划的正确信息,可以建议正确的选项。一些开始的建议:

升序键和自动快速更正统计- 例如,大表的一个常见统计问题是升序数据、日期和标识列。在上次更新统计信息后创建的数据过滤器可能会导致执行计划期望非常低的选择性,而实际上存在大量行。

提示和/或计划指南-OPTIMIZE FOR并且RECOMPILE可能适用于您的方案。KEEPFIXED PLAN可以与在计划的统计更新后立即强制重新编译结合使用。

计划强制- 捕获您的好计划,将其附加到问题查询中。

编辑:更新以下关于这是供应商应用程序的评论

这正是计划指南存在的原因,让 DBA 在无法修改源代码时有机会影响执行计划。有两种方法(均取自 BOL 的代码示例):

  • 创建对象(如果目标是存储过程)或 SQL 计划(如果匹配单个语句)指南,如理解计划指南中所述,并应用 OPTION 提示或通过捕获附加好的执行计划。

USE AdventureWorks2008R2;
GO
SELECT City, StateProvinceID, PostalCode FROM Person.Address ORDER BY PostalCode DESC;
GO
DECLARE @xml_showplan nvarchar(max);
SET @xml_showplan = (SELECT query_plan
    FROM sys.dm_exec_query_stats AS qs 
    CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
    CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle, DEFAULT, DEFAULT) AS qp
    WHERE st.text LIKE N'SELECT City, StateProvinceID, PostalCode FROM Person.Address ORDER BY PostalCode DESC;%');

EXEC sp_create_plan_guide 
    @name = N'Guide1_from_XML_showplan', 
    @stmt = N'SELECT City, StateProvinceID, PostalCode FROM Person.Address ORDER BY PostalCode DESC;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = @xml_showplan;
GO
Run Code Online (Sandbox Code Playgroud)

USE AdventureWorks2008R2;
GO
SELECT WorkOrderID, p.Name, OrderQty, DueDate
FROM Production.WorkOrder AS w 
JOIN Production.Product AS p ON w.ProductID = p.ProductID
WHERE p.ProductSubcategoryID > 4
ORDER BY p.Name, DueDate;
GO
-- Inspect the query plan by using dynamic management views.
SELECT * FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) AS qp
WHERE text LIKE N'SELECT WorkOrderID, p.Name, OrderQty, DueDate%';
GO
-- Create a plan guide for the query by specifying the query plan in the plan cache.
DECLARE @plan_handle varbinary(64);
DECLARE @offset int;
SELECT @plan_handle = plan_handle, @offset = qs.statement_start_offset
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS st
CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) AS qp
WHERE text LIKE N'SELECT WorkOrderID, p.Name, OrderQty, DueDate%';

EXECUTE sp_create_plan_guide_from_handle 
    @name =  N'Guide1',
    @plan_handle = @plan_handle,
    @statement_start_offset = @offset;
GO
-- Verify that the plan guide is created.
SELECT * FROM sys.plan_guides
WHERE scope_batch LIKE N'SELECT WorkOrderID, p.Name, OrderQty, DueDate%';
GO
Run Code Online (Sandbox Code Playgroud)