Sql-Server

SQL Server 2008 R2 中的 AUTO_UPDATE_STATISTICS 和 FULLSCAN

  • October 21, 2011

SQL Server 2008 R2自動FULLSCAN更新統計資訊時是否可以強制?

如果沒有,計劃UPDATE STATISTICS WITH FULLSCAN是保持統計數據最新的最佳方式嗎?

FULLSCAN注意:在使用非FULLSCAN統計數據時,需要通過已證明的次優計劃生成來實現。

自動更新始終使用從索引中的行數計算百分比的採樣。

從您的SO 文章中

Just FYI, the two indexes were PKs of tables having 280M+ and 55M+ rows, respectively.

我想這是 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
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

強制更新統計數據的一種非常直率的方式……

可能不需要全面掃描,只需要最新的統計資訊。現在,如果您有足夠的數據更改來觸發自動更新,那麼您可能也有邏輯碎片。

我會嘗試對使用的違規表/索引進行每小時線上索引建構

ALTER INDEX ALL ON ... WITH (ONLINE = ON)

注意:列統計資訊不會隨著索引重建而更新。但是如果你需要它們,你需要一個索引……

引用自:https://dba.stackexchange.com/questions/7051