操作員在溢出級別 2 的執行期間使用 tempdb 溢出數據
我正在努力使用警告
Operator used
tempdb最小化查詢計劃的排序操作成本to spill data during execution with spill level 2
我發現了幾篇與溢出級別 1 執行期間的溢出數據相關的文章,但不是級別 2。級別 1 似乎是由於統計數據過時造成的,那麼級別 2 呢?我找不到任何與
level 2
.我發現這篇與排序警告相關的文章非常有趣:
我的 Sql 伺服器?
Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64) 2016 年 6 月 17 日 19:14:09 版權所有 (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.3 (Build 9600:) (Hypervisor)
我的硬體?
執行以下查詢以查找硬體:
– 來自 SQL Server 2012 的硬體資訊
SELECT cpu_count AS [Logical CPU Count], hyperthread_ratio AS [Hyperthread Ratio], cpu_count/hyperthread_ratio AS [Physical CPU Count], physical_memory_kb/1024 AS [Physical Memory (MB)], affinity_type_desc, virtual_machine_type_desc, sqlserver_start_time FROM sys.dm_os_sys_info WITH (NOLOCK) OPTION (RECOMPILE);
目前分配的記憶體
SELECT (physical_memory_in_use_kb/1024) AS Memory_usedby_Sqlserver_MB, (locked_page_allocations_kb/1024) AS Locked_pages_used_Sqlserver_MB, (total_virtual_address_space_kb/1024) AS Total_VAS_in_MB, process_physical_memory_low, process_virtual_memory_low FROM sys.dm_os_process_memory;
當我在一年範圍內執行查詢時,我沒有收到任何警告,如下圖所示:
但是,當我只執行 1 天範圍時,我會收到以下警告
on the sort operator
:這是查詢:
DECLARE @FromDate SMALLDATETIME = '19-OCT-2016 11:00' DECLARE @ToDate SMALLDATETIME = '20-OCT-2016 12:00' SELECT DISTINCT a.strAccountCode , a.strAddressLine6 , a.strPostalCode , CASE WHEN a.strCountryCode IN ('91','92') THEN 'GB-Int' ELSE a.strCountryCode END AS [strCountryCode] FROM Bocss2.dbo.tblBAccountParticipant AS ap INNER JOIN Bocss2.dbo.tblBAccountParticipantAddress AS apa ON ap.lngParticipantID = apa.lngParticipantID AND apa.sintAddressTypeID = 2 INNER JOIN Bocss2.dbo.tblBAccountHolder AS ah ON ap.lngParticipantID = ah.lngParticipantID INNER JOIN Bocss2.dbo.tblBAddress AS a ON apa.lngAddressID = a.lngAddressID AND a.blnIsCurrent = 1 INNER JOIN Bocss2.dbo.tblBOrder AS o ON ap.lngParticipantID = o.lngAccountParticipantID AND o.sdtmOrdCreated >= @FromDate AND o.sdtmOrdCreated < @ToDate OPTION(RECOMPILE)
問題:1)在查詢計劃中我看到了這個:
StatementOptmEarlyAbortReason="GoodEnoughPlanFound" CardinalityEstimationModelVersion="70"
為什麼是70?我正在使用 sql server 2014
2)我如何擺脫那個排序運算符(如果可能的話)?
- 我看到頁面壽命預期非常低,除了向該伺服器添加更多記憶體之外,還有什麼其他的東西我可以看看我是否可以阻止這個警告?
乾杯
在 Shanky 和 Paul White 的回答之後更新
我已經根據下面的腳本檢查了我的統計數據,它們似乎都是正確和更新的。
這些都是此查詢中使用的所有索引和表。
DBCC SHOW_STATISTICS ('dbo.tblBAddress','IDXF_tblBAddress_lngAddressID__INC') GO DBCC SHOW_STATISTICS ('dbo.tblBOrder','IX_tblBOrder_sdtmOrdCreated_INCL') GO DBCC SHOW_STATISTICS ('dbo.tblBAccountHolder','PK_tblAccountHolder') GO DBCC SHOW_STATISTICS ('dbo.tblBAccountParticipant','PK_tblBAccountParticipants') GO DBCC SHOW_STATISTICS ('dbo.tblBAccountParticipantAddress','IDXF_tblBAccountParticipantAddress_lngParticipantID') GO
這是我得到的回報:
這是部分結果,但我已全部重新訪問。
對於統計更新,我目前有Ola Hallengren
索引優化作業 - 計劃每週執行一次 - 星期日
EXECUTE [dbo].[IndexOptimize] @Databases = 'USER_DATABASES,-%Archive', @Indexes = 'ALL_INDEXES' , @FragmentationLow = NULL, @FragmentationMedium = NULL, @FragmentationHigh = NULL, @PageCountLevel=1000, @StatisticsSample =100 ,@UpdateStatistics = 'Index', @OnlyModifiedStatistics = 'Y', @TimeLimit=10800, @LogToTable = 'Y'
儘管統計資訊似乎已更新,但在我執行以下腳本後,我不再收到有關排序運算符的警告。
UPDATE STATISTICS [Bocss2].[dbo].[tblBOrder] WITH FULLSCAN --1 hour 04 min 14 sec UPDATE STATISTICS [Bocss2].[dbo].tblBAddress WITH FULLSCAN -- 45 min 29 sec UPDATE STATISTICS [Bocss2].[dbo].tblBAccountHolder WITH FULLSCAN -- 26 SEC UPDATE STATISTICS [Bocss2].[dbo].tblBAccountParticipant WITH FULLSCAN -- 4 min UPDATE STATISTICS [Bocss2].[dbo].tblBAccountParticipantAddress WITH FULLSCAN -- 7 min 3 sec
2級呢?我找不到與 2 級相關的任何內容。
根據這個 Old MS Doc,Tempdb 溢出中的數字表示需要對數據進行多少次傳遞才能對數據進行排序。所以 Spill 1 意味著它必須經過 1 次才能對數據進行排序,2 意味著它必須經過 2 次。
引用部落格:
如果涉及排序操作的查詢生成溢出級別值為 2 的排序警告事件類,則查詢的性能可能會受到影響,因為需要多次傳遞數據才能對數據進行排序。在下面的範例中,我們看到溢出級別值為 1,這意味著通過數據一次就足以完成排序。
為什麼是70?我正在使用 sql server 2014
這是因為圖片中數據庫的兼容級別不是 120(表示 2014 數據庫的兼容級別),因為它不是 120,查詢將使用舊的基數估計 (CE) 模型進行處理,稱為
CardinalityEstimationModelVersion="70"
. 我相信您知道從 SQL Server 2014 開始我們有了新的 CE。我如何擺脫那個排序運算符(如果可能的話)?
您正在使用的 distinct 命令導致排序操作。正在排序的數據不適合記憶體,因此它會溢出到 tempdb,當這種情況發生時,執行計劃中會給出帶有黃色驚嘆號的排序警告。排序警告並不總是一個問題。
您可以在執行計劃中看到,估計要排序的行數為 1,但在執行時遇到了 16,353 行。為排序保留的記憶體量基於輸入的預期(估計)大小,並且在執行期間不能增長(在這種情況下)。
查詢的小記憶體授權 (1632KB) 也在並發執行的記憶體消耗運算符(排序和*“優化”循環連接)之間共享。在您的計劃中,這意味著 33.33% (544KB) 在讀取行時可用於排序(輸入記憶體部分)。這沒有足夠的記憶體來對 16,353 行進行排序,因此它會溢出到tempdb*。單級溢出不足以完成排序,因此需要第二級溢出(有關溢出級別的更多詳細資訊,請參閱末尾的參考資料)。
對在 SQL Sentry Plan Explorer 中查看的屬性進行排序
更新統計數據可能有助於解決基數估計問題。您可能會遇到升序鍵問題,尤其是在 table 上
tblBOrder
。從該表中選擇一個帶有您問題的文字日期的簡單選擇,現在可能會估計一行。我已經看到頁面壽命預期非常低,除了向該伺服器添加更多記憶體之外,還有什麼其他的東西我可以看看我是否可以防止這個警告?
PLE 是 I/O 活動量的指示,它是否增加了?因此,這種情況經常發生還是僅在您執行某些查詢時發生或僅在今天發生。避免膝跳反應,首先我們需要確保您確實面臨記憶體壓力或一些產生過多 I/O 的惡意查詢導致這種情況。無論如何,您已經為 SQL Server 分配了 97 G 記憶體。
有關溢出水平和上升關鍵問題的更多資訊,請參閱:
- 溢出到 15,000 級的排序Paul White
- 法比亞諾·阿莫林(Fabiano Amorim )的升序統計