流出をtempdbにソートしますが、推定行は実際の行と等しくなります


14

最大メモリを25GBに設定したSQL Server 2016 SP2では、1分間に約80回実行されるクエリがあります。クエリにより、約4000ページがtempdbに流出します。これにより、tempdbのディスクで大量のIOが発生します。

あなたが見てとるときにクエリプラン(簡体クエリを)あなたは、推定行数は実際の行数と同じであるが、依然として発生こぼれることがわかります。したがって、古い統計が問題の原因になることはありません。

私はいくつかのテストを行い、次のクエリをTempdbにスピルしました。

select id --uniqueidentifier
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)

しかし、別の列を選択した場合、流出は発生しません。

select startdate --datetime
from SortProblem
where [status] ='A'
order by SequenceNumber asc 
option (maxdop 1)

そこで、id列のサイズを「拡大」しようとしました。

select CONVERT(nvarchar(512),id)
from SortProblem
where [status] ='A'
order by SequenceNumber asc 
option (maxdop 1)

その後、こぼれも発生しません。

uniqueidentifierがtempdbに流出し、datatime列が流出しないのはなぜですか?約20000個のレコードを削除すると、id列を選択してもスピルは発生しません。

次のスクリプトを使用すると、問題を再現できます。

CREATE TABLE SortProblem
  (
     id             UNIQUEIDENTIFIER,
     startdate      DATETIME,
     sequencenumber BIGINT,
     status         VARCHAR(50),
     PRIMARY KEY CLUSTERED(id)
  )

SET nocount ON;

WITH nums(num)
     AS (SELECT TOP 103000 ROW_NUMBER()
                             OVER (
                               ORDER BY 1/0)
         FROM   sys.all_objects o1,
                sys.all_objects o2)
INSERT INTO SortProblem
SELECT newid(),
       DATEADD(millisecond, num, GETDATE()),
       num,
       CASE
         WHEN num <= 100000 THEN 'A'
         WHEN num <= 101000 THEN 'B'
         WHEN num <= 102000 THEN 'C'
         WHEN num <= 103000 THEN 'D'
       END
FROM   nums

CREATE NONCLUSTERED INDEX [IX_Status]
  ON [dbo].[SortProblem]([status] ASC)
  INCLUDE ([sequencenumber]) 

回答:


14

トレースフラグ7470を有効にします。

修正:推定行数と行サイズが正しい場合、SQL Server 2012またはSQL Server 2014でソート演算子がtempdbに流出する

クエリプランの質問への回答で書いたように:

このトレースフラグは、計算の見落としを修正します。使用するのは非常に安全であり、私の意見ではデフォルトでオンになっているはずです。予期しない計画変更を避けるために、変更はトレースフラグによって保護されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.