私は私の問題が何であるかを示すことができるように例を作りました:
セットアップ:
CREATE TABLE [dbo].[Test](
[TestId] [bigint] IDENTITY(1,1) NOT NULL,
[ParentTestId] [bigint] NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED ([TestId] ASC)
)
GO
ALTER TABLE [dbo].[Test] WITH CHECK ADD CONSTRAINT [FK_Test_ParentTest]
FOREIGN KEY([ParentTestId])
REFERENCES [dbo].[Test] ([TestId])
GO
ALTER TABLE [dbo].[Test] CHECK CONSTRAINT [FK_Test_ParentTest]
GO
DECLARE @iter INT
SET @iter = 1
WHILE @iter < 1000
BEGIN
INSERT INTO dbo.Test ( ParentTestId )
VALUES ( null ),( null ),( null ),( null ),( null ),( null ),( null ),( null ),
( null ),( null ),( null ),( null ),( null ),( null ),( null ),( null ),( null ),
( null ),( null ),( null ),( null ),( null ),( null ),( null ),( null ),( null ),
( null ),( null ),( null ),( null ),( null ),( null ),( null ),( null ),( null ),
( null ),( null ),( null ),( null ),( null ),( null ),( null ),( null ),( null )
SET @iter = @iter + 1
END
go
これにより、自己参照テーブルが作成され、40,000を超える行が追加されます。
アクション:
DELETE FROM dbo.Test WHERE TestId = 200
次に、このテーブルから行を削除します。実際のクエリプランをオンにして上記のステートメントを実行すると、自己参照キーのクラスタ化インデックススキャンでコストの20%が使用されていることがわかります。
これはこのシナリオでは大したことではありませんが、私の実際のシナリオでは、大きなテーブルに2,500万行以上あります。
だから、私は2つの質問があります:
編集:これは、SQL Serverが、削除中の行を他の行が参照しているかどうかを確認しようとしているためと考えられました。しかし、「外部キー制約を強制する」を「いいえ」に設定しましたが、それでもクラスター化インデックススキャンと同じコストがかかりました。
削除しようとしている行が既存の行の親ではないことを検証する必要があります。
ParentTestId
にインデックスがありません。
したがって、スキャンを実行する必要があります。
CREATE NONCLUSTERED INDEX ix ON [dbo].[Test](ParentTestId)
その後、シークが表示されます。
ところで、この場合、スキャンの推定コストの20%は過小評価される可能性があります。
FK検証は左側の準結合の下にあり、SQL Serverは部分的なスキャンのみが必要であり、一致する行を見つけて削除が失敗するかのようにコストがかかります。
おそらく、実際に削除している行は成功する頻度が高いため、競合する行がないことを検証するためにフルスキャンが必要になります。
トレースフラグ4138
を使用して行の目標をオフにする
DELETE FROM dbo.Test
WHERE TestId = 200
OPTION (querytraceon 4138 )
再計算されたプランでは、CIスキャンが20%ではなく100%で示されます(現在、フルスキャンが必要であると想定されているため)。
推定コストのこの違いは、欠落しているインデックスの提案が表示されるのに十分です。
ただし、この計画に示されているコストは、まだそれほど代表的なものではありません。合計が219%になっていることに気付くでしょう。
また、トレースフラグがある場合とない場合のクエリの全体的な計画コストは、0.0168268
でも同じです。完全なCIスキャンは、実際には0.152373
(0.0485075 + 0.103866
)で行う必要があります。
ただし、上限は元の計画コスト以下であるようです(全体の計画コストは上方調整されないため、パーセンテージも正しくありません)。