2017-08-25 109 views
0

我支持每天晚上運行的流程,並查看具有未付訂單項的發票的各種客戶。該流程從刪除登臺表中的所有記錄開始,然後將多個發票行項目插入登臺表中。該流程基於每個客戶端運行,因此某些客戶可能有200個訂單項,某些客戶可能有50,000個。我們在這個過程中經常遇到很多問題。這個問題似乎源於SQL Server無法估計當時登臺表中正確的行數,因此會產生錯誤的執行計劃。我的問題是,是否有辦法手動設置估計的行數以提高存儲過程的基數估計值?也許這可以在運行開始時通過選擇計數(primaryKey)完成,在當前運行臨時表填充之後立即執行?如何提高登臺表上的基數估計值?

+1

如果您要刪除並插入並且不從臨時表中選擇;爲什麼SQL會使用臨時表中的統計數據?也許我錯過了一些東西;但除非您正在執行選擇或合併,並基於登臺表中的數據進行插入/刪除,爲什麼它的統計數據很重要?或者你是在刪除/插入完成後說話,那麼你在分段表上進行分析很慢?你是否在表格/索引視圖上試過強制更新? https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-updatestats-transact-sql – xQbert

+1

在進程啓動之前,您可以嘗試更新表上的統計信息。 https://docs.microsoft.com/en-us/sql/t-sql/statements/update-statistics-transact-sql。更新統計信息後,您可以重新編譯任何存儲過程以強制SQL提出新的執行計劃。 https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-recompile-transact-sql – Jason

+1

刪除所有行並重新填充它將導致統計信息被更新。也許你遇到參數嗅探,其中不同的客戶端有很大的不同行數,但是這個計劃是爲遇到的第一個客戶端編譯的。在這種情況下,將「OPTION(RECOMPILE)」添加到問題查詢中會有所幫助。 –

回答

1

您正在此表上執行大批量進程。在批次之前刪除所有索引並在批次之後再次創建它們是一種好方法。

如果你這樣做,你的統計數據將被更新,而不會成爲你的問題的原因。

還需要注意統計信息的更一般信息:更新統計信息在SQL Server 2014和SQL Server 2016之間有很大變化。如果您運行的是SQL Server 2016,則需要檢查數據庫是否使用新基數估計器爲SQL Server 2016創建。請檢查您的數據庫是否正在運行SQL Server 2016兼容級別。

如果您正在運行SQL Server 2014,一個不錯的選擇是啓用跟蹤標誌2371.此跟蹤標誌改進了SQL Server用於自動更新統計信息的標準。您應該使用SQL Server配置管理器來啓用此跟蹤標誌。

但是,如果您按照第一個建議刪除並創建索引,那麼另外兩個建議的影響就會很小或沒有影響。

+0

爲什麼要刪除並重新創建索引而不是禁用並重建它們? – alroc

+0

Sql Server 2008. –

+1

@alroc如果禁用聚簇索引,表將變爲只讀。 –