1つの方法は、値に#tempテーブルを使用し、ダミーの等価結合列を導入してハッシュ結合を可能にすることです。例えば:
-- Create a #temp table with a dummy column to match the hash join
-- and the actual column you want
CREATE TABLE #values (dummy INT NOT NULL, Col0 CHAR(1) NOT NULL)
INSERT INTO #values (dummy, Col0)
VALUES (0, 'A'),
(0, 'B'),
(0, 'C')
GO
-- A similar query, but with a dummy equijoin condition to allow for a hash join
SELECT v.Col0,
CASE v.Col0
WHEN 'A' THEN cs.DataA
WHEN 'B' THEN cs.DataB
WHEN 'C' THEN cs.DataC
END AS Col1
FROM ColumnstoreTable cs
JOIN #values v
-- Join your dummy column to any numeric column on the columnstore,
-- multiplying that column by 0 to ensure a match to all #values
ON v.dummy = cs.DataA * 0
パフォーマンスとクエリプラン
このアプローチでは、次のようなクエリプランが生成され、ハッシュモードはバッチモードで実行されます。
私が交換した場合SELECT
との声明をSUM
するCASE
私が転がっているコンソールにすべてのそれらの行をストリーミングして、実際の100MM行columnstoreテーブルにクエリを実行するのを避けるために声明、私は必要な300MMを生成するために、かなり良好なパフォーマンスを参照してください行:
CPU time = 33803 ms, elapsed time = 4363 ms.
そして、実際の計画では、ハッシュ結合の適切な並列化が示されています。
すべての行が同じ値を持つ場合のハッシュ結合並列化に関する注意
このクエリのパフォーマンスは、完全なハッシュテーブルにアクセスできる結合のプローブ側の各スレッドに大きく依存します(ハッシュパーティションバージョンでは、1つの異なる値しかない場合にすべての行を1つのスレッドにマップします)以下のためのdummy
コラム)。
幸いなことに、これはこの場合に当てはまり(Parallelism
プローブ側に演算子がないことからわかるように)、バッチモードはスレッド間で共有される単一のハッシュテーブルを構築するため、確実に当てはまるはずです。したがって、各スレッドはから行を取得Columnstore Index Scan
し、その共有ハッシュテーブルと一致させることができます。SQL Server 2012では、こぼれによりオペレーターが行モードで再起動し、バッチモードの利点を失い、Repartition Streams
この場合スレッドスキューを引き起こす結合のプローブ側にオペレーターを必要とするため、この機能の予測性ははるかに低くなりました。 。流出をバッチモードのままにしておくことは、SQL Server 2014の大幅な改善です。
私の知る限り、行モードにはこの共有ハッシュテーブル機能はありません。ただし、通常、ビルド側の推定行数が100行未満の場合、SQL Serverは各スレッドのハッシュテーブルの個別のコピーを作成します(Distribute Streams
ハッシュ結合の先頭で識別可能)。これは非常に強力ですが、カーディナリティの見積もりに依存し、SQL Serverは各スレッドのハッシュテーブルの完全なコピーを構築する利点とコストを評価しようとするため、バッチモードよりも信頼性がはるかに低くなります。
UNION ALL:より単純な代替
Paul Whiteは、別の、場合によってはより単純なオプションを使用UNION ALL
して、各値の行を結合することを指摘しました。これはおそらく、このSQLを動的に構築するのが簡単だと仮定した場合の最善策です。例えば:
SELECT 'A' AS Col0, c.DataA AS Col1
FROM ColumnstoreTable c
UNION ALL
SELECT 'B' AS Col0, c.DataB AS Col1
FROM ColumnstoreTable c
UNION ALL
SELECT 'C' AS Col0, c.DataC AS Col1
FROM ColumnstoreTable c
これにより、バッチモードを利用できるプランが得られ、元の回答よりも優れたパフォーマンスが得られます。(どちらの場合もパフォーマンスは十分に速いので、データを選択したりテーブルに書き込むとすぐにボトルネックになります。)このUNION ALL
アプローチでは、0を掛けるなどのゲームをすることも避けられます。
CPU time = 8673 ms, elapsed time = 4270 ms.