なぜこのストリーム集約が必要なのですか?


12

このクエリをご覧ください。それは非常に簡単です(テーブルとインデックスの定義、および再現スクリプトについては投稿の最後をご覧ください):

SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1 AND 1 = (SELECT 1);

注:「AND 1 =(SELECT 1)は、このクエリが自動パラメータ化されないようにするためのものです。これは問題を混乱させているように感じました。

そして、これがプランです(プランのリンクを貼り付けてください)

ストリームaggで計画する

そこには「トップ1」があるので、ストリーム集約演算子を見て驚いた。1行のみであることが保証されているので、私には必要ないようです。

その理論をテストするために、この論理的に同等のクエリを試しました。

SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1
GROUP BY Id;

これがその計画です(計画のリンクを貼り付けてください):

ストリーム集約なしで計画する

案の定、group by planは、ストリーム集約演算子なしで対応できます。

両方のクエリがインデックスの最後から「後方」を読み取り、「トップ1」を実行して最大リビジョンを取得することに注意してください。

ここで何が欠けていますか? ストリーム集合体は最初のクエリで実際に動作するのですか、それとも排除する必要がありますか(それはオプティマイザーの制限であり、そうではありません)?

ちなみに、これは信じられないほど実用的な問題ではないことを認識しています(クエリは両方ともCPUの0ミリ秒と経過時間を報告します)。


上記の2つのクエリを実行する前に実行したセットアップコードを次に示します。

DROP TABLE IF EXISTS dbo.TheOneders;
GO

CREATE TABLE dbo.TheOneders
(
    Id INT NOT NULL,
    Revision SMALLINT NOT NULL,
    Something NVARCHAR(23),

    CONSTRAINT PK_TheOneders PRIMARY KEY NONCLUSTERED (Id, Revision)
);
GO

INSERT INTO dbo.TheOneders
    (Id, Revision, Something)
SELECT DISTINCT TOP 1000 
    1, m.message_id, 'Do...'
FROM sys.messages m
ORDER BY m.message_id
OPTION (MAXDOP 1);

INSERT INTO dbo.TheOneders
    (Id, Revision, Something)
SELECT DISTINCT TOP 100 
    2, m.message_id, 'Do that thing you do...'
FROM sys.messages m
ORDER BY m.message_id
OPTION (MAXDOP 1);
GO

回答:


16

WHERE句に一致する行がない場合、この集約の役割を確認できます。

SELECT MAX(Revision)
FROM   dbo.TheOneders
WHERE  Id = 1
       AND 1 = 1 /*To avoid auto parameterisation*/
       AND Id%3 = 4  /*always false*/

その場合、集計に含まれる行はゼロになりますがNULL、この場合は正しいセマンティクスが返されるため、まだ1行が出力されます。

ここに画像の説明を入力してください

これは、ベクトル1とは対照的なスカラー集約です。

「論理的に同等」のクエリは同等ではありません。追加するGROUP BY Idと、それはベクトル集合になり、正しい動作は行を返さないことです。

これについて詳しくは、Fun with Scalar and Vector Aggregatesをご覧ください。

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