web-dev-qa-db-ja.com

オペレーターは実行中にtempdbを使用して、スピルレベル2でデータをスピルしました

警告Operator usedtempdbto spill data during execution with spill level 2を使用して、クエリプランでの並べ替え操作のコストを最小限に抑えるのに苦労しています。

スピルレベル1で実行中のスピルデータ に関連するいくつかの投稿を見つけましたが、レベル2ではありません。 レベル1は古い統計が発生しているようです 、レベル2はどうですか? level 2に関連するものは見つかりませんでした。

この記事はソートの警告に関連して非常に興味深いものでした:

SQL Serverでソート警告を無視しない

My SQL Server?

Microsoft SQL Server 2014(SP2)(KB3171021)-12.0.5000.0(X64)2016年6月17日19:14:09 Copyright(c)Microsoft Corporation Enterprise Edition(64-bit)on Windows NT 6.3(Build 9600:)(Hypervisor)

My Hardware?

以下のクエリを実行して、ハードウェアを見つけます。

-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);

enter image description here

現在割り当てられているメモリ

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;

enter image description here

1年のスコープでクエリを実行すると、次の図のように警告がまったく表示されません。

enter image description here

しかし、1日間のスコープでのみ実行すると、次の警告が表示されますon the sort operator

enter image description here

これはクエリです:

    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)

クエリプランはこちら

pastetheplanを使用したクエリプラン

質問:1)クエリプランに次のように表示されます。

StatementOptmEarlyAbortReason="GoodEnoughPlanFound" CardinalityEstimationModelVersion="70" 

なぜ70? SQL Server 2014を使用しています

2)(可能な場合)どうすればそのソート演算子を取り除くことができますか?

3)このサーバーにメモリを追加することを除けば、ページ寿命の期待値はかなり低くなっています。この警告を回避できるかどうかを確認するために他に確認できることはありますか?

乾杯

シャンキーとポールホワイトからの回答の後に更新します

以下のスクリプトに従って統計を確認しましたが、すべて正しく更新されているようです。

これらはすべて、このクエリで使用されるインデックスとテーブルです。

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

これは私が戻ってきたものです:

enter image description here

enter image description here

これは部分的な結果ですが、すべて再確認しました。

統計の更新について、私は現在 Ola Hallengren を持っています

インデックス最適化ジョブ-週に1回実行するようにスケジュール-日曜日

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
18

レベル2はどうですか?レベル2に関連するものは何も見つかりませんでした。

this Old MS Doc のように、Tempdbスピルの数値は、データをソートするためにデータに対して必要なパスの数を示します。つまり、スピル1は、データをソートするために1回渡す必要があることを意味し、2は、2回渡す必要があることを意味します。

ブログからの引用:

並べ替え操作を含むクエリで、スピルレベルの値が2の並べ替え警告イベントクラスが生成された場合、データを並べ替えるにはデータを複数回渡す必要があるため、クエリのパフォーマンスに影響する可能性があります。以下の例では、スピルレベルの値が1であることを示しています。これは、データを1回パスするだけでソートを完了するのに十分であることを意味します。

なぜ70? SQL Server 2014を使用しています

これは、図のデータベースの互換性レベルが120(2014データベースの互換性レベルを示す)ではないためです。120ではないため、クエリは、CardinalityEstimationModelVersion="70"と呼ばれる古いカーディナリティ推定(CE)モデルを使用して処理されます。 SQL Server 2014以降、新しいCEがあることをご存じでしょう。

そのソート演算子を取り除くにはどうすればよいですか(可能な場合)?

使用している個別のコマンドがソート操作を引き起こしています。ソートされているデータがメモリに収まらないため、tempdbに流出し、これが発生すると、黄色の感嘆符付きのソート警告が実行プランに表示されます。ソート警告は常に問題になるとは限りません。

ソートされる行の推定数は1ですが、実行時に16,353が発生することが実行プランで確認できます。ソート用に予約されているメモリの量は、入力のexpected(推定)サイズに基づいており、実行中に(この場合)大きくすることはできません。

クエリの小さなメモリ許可(1632KB)は、同時に実行されるメモリ消費演算子(ソートおよび 'optimized'ループ結合)の間でも共有されます。計画では、これは、行(入力メモリ部分)の読み取り中に33.33%(544KB)がソートに使用できることを意味します。これは、16,353行を並べ替えるのに十分なメモリではないため、tempdbに溢れます。単一レベルの流出では分類を完了するのに十分ではないため、流出の第2レベルが必要です(流出レベルの詳細については、最後にあるリファレンスを参照してください)。

Sort properties

SQL Sentry Plan Explorerで表示されるプロパティの並べ替え

統計を更新すると、カーディナリティの推定の問題が解決する可能性があります。特にテーブルtblBOrderで、昇順のキーの問題が発生している可能性があります。質問からの日付のリテラルを含むそのテーブルからの単純な選択は、おそらく現在1行を推定します。

このサーバーにメモリを追加することを除けば、ページ寿命の期待値はかなり低くなっています。この警告を回避できるかどうかを確認するために他に確認できることがありますか?

PLEは、I/Oアクティビティの量を示していますが、増加していますか?そのため、これが頻繁に発生するのは、特定のクエリを実行したとき、またはこれが今日発生したときだけです。ひどい反応を避けてください。最初に、メモリのプレッシャーに直面していることを確認する必要があります。または、I/Oを生成しすぎている不正なクエリが原因となっていることを確認する必要があります。とにかく、SQL Serverに97 Gのメモリが割り当てられています。

流出レベルと昇順のキーの問題の詳細については、以下を参照してください。

17
Shanky