SQL Server 2012(11.0.6020)にかなり単純なテストベッドを構築すると、2つのハッシュ一致クエリがを介して連結されたプランを再作成できますUNION ALL
。私のテストベッドには、間違った見積もりが表示されません。おそらくこれは SQL Server 2014 CEの問題です。
実際に280行を返すクエリに対して133.785行の推定値が得られますが、これについては後で詳しく説明します。
IF OBJECT_ID('dbo.Union1') IS NOT NULL
DROP TABLE dbo.Union1;
CREATE TABLE dbo.Union1
(
Union1_ID INT NOT NULL
CONSTRAINT PK_Union1
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, Union1_Text VARCHAR(255) NOT NULL
, Union1_ObjectID INT NOT NULL
);
IF OBJECT_ID('dbo.Union2') IS NOT NULL
DROP TABLE dbo.Union2;
CREATE TABLE dbo.Union2
(
Union2_ID INT NOT NULL
CONSTRAINT PK_Union2
PRIMARY KEY CLUSTERED
IDENTITY(2,2)
, Union2_Text VARCHAR(255) NOT NULL
, Union2_ObjectID INT NOT NULL
);
INSERT INTO dbo.Union1 (Union1_Text, Union1_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;
INSERT INTO dbo.Union2 (Union2_Text, Union2_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;
GO
SELECT *
FROM dbo.Union1 u1
INNER HASH JOIN sys.objects o ON u1.Union1_ObjectID = o.object_id
UNION ALL
SELECT *
FROM dbo.Union2 u2
INNER HASH JOIN sys.objects o ON u2.Union2_ObjectID = o.object_id;
理由は、UNIONになっている2つの結果の結合の統計情報の不足にあると思います。SQL Serverは、ほとんどの場合、統計の欠如に直面したときの列の選択性に関する知識に基づいた推測を行う必要があります。
ジョーサックの興味深い記事がここにあります。
aのUNION ALL
場合、ユニオンの各コンポーネントによって返された行の合計数を正確に表示すると言っても安全ですが、SQL Serverはの2つのコンポーネントに対して行推定を使用しているため、両方のUNION ALL
合計推定行を追加することがわかります連結演算子の推定値を求めるクエリ。
上記の私の例では、の各部分の推定行数UNION ALL
は66.8927であり、合計すると133.785になり、連結演算子の推定行数で見ることができます。
上記のユニオンクエリの実際の実行計画は次のようになります。
「推定」対「実際」の行数を確認できます。私の場合、2つのハッシュ一致演算子によって返される「推定」数の行を追加すると、連結演算子によって示される量と正確に等しくなります。
質問で示したPaul Whiteの投稿で推奨されているように、トレース2363などから出力を取得しようとします。あるいは、OPTION (QUERYTRACEON 9481)
クエリでを使用してバージョン70 CEに戻り、問題が「修正」されるかどうかを確認することもできます。