web-dev-qa-db-ja.com

バッチモードは、ColumnStoreインデックスのAgg関数にのみ適用されますか?

Azure SQLデータベース-StandardEdition(S3サービス層)

集計関数を使用している場合にのみバッチモードが有効になるのはなぜですか?

DROP TABLE IF EXISTS dbo.TransCS

CREATE TABLE dbo.TransCS (
     Col1 INT 
    ,Col2 AS Col1*2
)
CREATE CLUSTERED COLUMNSTORE INDEX CS_TransCS on dbo.TransCS;

WITH
    L0   AS(SELECT 1 AS c UNION ALL SELECT 1),
    L1   AS(SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
    L2   AS(SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
    L3   AS(SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
    L4   AS(SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
    L5   AS(SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
    Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) 
    AS n FROM L5)
INSERT INTO dbo.TransCS (Col1)
SELECT TOP (1000000) n FROM Nums ORDER BY n; 

100万行を挿入します

行処理

SELECT * FROM dbo.TransCS

実行計画

バッチ処理

SELECT Col1, Col2, SUM(Col2)OVER ()
FROM dbo.TransCS

実行計画

Agg関数を使用せずにパフォーマンス上の利点を利用する方法はありますか?これに関するドキュメントは薄いです。

2
Geezer

バックグラウンド

2017年7月に、Niko ブログについて SQL Server2017の変更

... SQL Server 2017には、クエリオプティマイザーの内部最適化があり、列ストアインデックスを使用して実行プランに完全な最適化を適用し、行実行モードで実行する際の落とし穴を回避します。

それ以前は、列ストアオブジェクトが含まれている場合でも、「トリビアルプラン」に対して行モードで実行されていました。

共有した実行プランは、最初のクエリにこの問題があることを示しています。これはXMLで確認できます。

StatementOptmLevel="TRIVIAL" 

Workaround

これを回避し、完全な最適化を取得して、バッチモードスキャンを取得する1つの方法は、次のように、結果に影響を与えないサブクエリを追加することです。

SELECT * FROM dbo.TransCS WHERE (SELECT 1) = 1;

2番目のクエリは、集計関数のためにすでに完全に最適化されています。

なんでこんなことが起こっているの?

これが発生する理由について頭に浮かぶのは、次のとおりです。

  • データベースの互換性レベルが130以下である(実行プランで140カーディナリティ推定量が使用されていることがわかるため、これはありそうにないようです)
  • これは、特にAzure SQLDatabaseの変更/リグレッションです
    • 実行プランに示されている「ビルド」は15.0.1100.504、これはSQL Server 2019のビルド番号のように見えます(これはAzureであるため、意味があります)。テストする2019インスタンスはありませんが、動作の変化もある可能性があります

フィードバックサイト でMicrosoftに報告することをお勧めします。

3
Josh Darnell