次のようなクエリがあります。
DELETE FROM tblFEStatsBrowsers WHERE BrowserID NOT IN (
SELECT DISTINCT BrowserID FROM tblFEStatsPaperHits WITH (NOLOCK) WHERE BrowserID IS NOT NULL
)
tblFEStatsBrowsersには553行あります。
tblFEStatsPaperHitsには47.974.301行があります。
tblFEStatsBrowsers:
CREATE TABLE [dbo].[tblFEStatsBrowsers](
[BrowserID] [smallint] IDENTITY(1,1) NOT NULL,
[Browser] [varchar](50) NOT NULL,
[Name] [varchar](40) NOT NULL,
[Version] [varchar](10) NOT NULL,
CONSTRAINT [PK_tblFEStatsBrowsers] PRIMARY KEY CLUSTERED ([BrowserID] ASC)
)
tblFEStatsPaperHits:
CREATE TABLE [dbo].[tblFEStatsPaperHits](
[PaperID] [int] NOT NULL,
[Created] [smalldatetime] NOT NULL,
[IP] [binary](4) NULL,
[PlatformID] [tinyint] NULL,
[BrowserID] [smallint] NULL,
[ReferrerID] [int] NULL,
[UserLanguage] [char](2) NULL
)
BrowserIDを含まないtblFEStatsPaperHitsにはクラスター化インデックスがあります。したがって、内部クエリを実行するには、tblFEStatsPaperHitsの全テーブルスキャンが必要になります。これはまったく問題ありません。
現在、tblFEStatsBrowsersの各行に対してフルスキャンが実行されています。つまり、tblFEStatsPaperHitsの553のフルテーブルスキャンがあります。
WHERE EXISTSに書き換えても計画は変わりません。
DELETE FROM tblFEStatsBrowsers WHERE NOT EXISTS (
SELECT * FROM tblFEStatsPaperHits WITH (NOLOCK) WHERE BrowserID = tblFEStatsBrowsers.BrowserID
)
ただし、Adam Machanicが示唆しているように、HASH JOINオプションを追加すると、最適な実行計画(tblFEStatsPaperHitsの1回のスキャンのみ)になります。
DELETE FROM tblFEStatsBrowsers WHERE NOT EXISTS (
SELECT * FROM tblFEStatsPaperHits WITH (NOLOCK) WHERE BrowserID = tblFEStatsBrowsers.BrowserID
) OPTION (HASH JOIN)
これは、これをどのように修正するかという問題ではありません。OPTION(HASH JOIN)を使用するか、一時テーブルを手動で作成できます。クエリオプティマイザーが現在実行しているプランを使用するのはなぜだろうと思います。
QOのBrowserID列には統計情報がないため、最悪の場合-5000万の異なる値を想定しているため、かなり大きなメモリ内/ tempdbワークテーブルが必要です。そのため、最も安全な方法は、tblFEStatsBrowsersで各行のスキャンを実行することです。2つのテーブルのBrowserID列間に外部キー関係はないため、QOはtblFEStatsBrowsersから情報を差し引くことができません。
これは、見た目と同じくらい単純なのでしょうか?
更新1
いくつかの統計情報を提供するには:OPTION(HASH JOIN):
208.711論理読み取り(12スキャン)
オプション(ループ結合、
ハッシュグループ):11.008.698論理読み取り(BrowserID(339)ごとにスキャン)
オプションなし:
11.008.775論理読み取り(〜BrowserID(339)ごとにスキャン)
更新2
すばらしい回答、皆さん-ありがとう!1つだけを選ぶのは難しい。マーティンが最初であり、レムスは優れたソリューションを提供しますが、詳細をメンタルに伝えるためにキウイに提供する必要があります:)