次のようなSQLクエリがあります。
SELECT A, B, (CASE WHEN C=0 THEN 0 ELSE 1 END), COUNT(D)
FROM SomeTable
GROUP BY A, B, (CASE WHEN C=0 THEN 0 ELSE 1 END)
巨大なデータセットでは、実際の実行プランは、ほとんどの場合論理演算Aggregateおよび物理演算HashMatchに対応するノードに帰属します。
列と条件がGROUP BY
リストにリストされている順序を変更すると、パフォーマンスに影響がありますか?
MSDNのドキュメントに書かれていることに関わらず、いいえ、GROUP BY
クエリ。
次の場所でテストできます SQL-Fiddle test(SQL-Server 2012)
CREATE TABLE test
( id INT IDENTITY(1,1)
, a INT NOT NULL
, b INT NOT NULL
, c INT NOT NULL
, d INT NOT NULL
, PRIMARY KEY (id)
) ;
CREATE NONCLUSTERED INDEX a_b_c_include_d_index
ON test (a, b, c)
INCLUDE (d) ;
INSERT INTO test
(a, b, c, d)
VALUES
... some 50K rows
クエリ:
SELECT COUNT(*) AS num
, MIN(cnt) AS min_count
, MAX(cnt) AS max_count
, MIN(min_d) AS min_min_d
, MAX(min_d) AS max_min_d
, MIN(max_d) AS min_max_d
, MAX(max_d) AS max_max_d
FROM
( SELECT a
, b
, c
, COUNT(d) AS cnt
, MIN(d) AS min_d
, MAX(d) AS max_d
FROM test
GROUP BY a, b, c --- or with: `GROUP BY b, a, c`
) AS grp ;
同じ実行計画を作成します。
Microsoft SQL SERVER 2005 XML SHOWPLAN
SELECT
Compute Scalar
Cost: 0%
Stream Aggregate
(Aggregate)
Cost: 0%
Compute Scalar
Cost: 10%
Stream Aggregate
(Aggregate)
Cost: 10%
Index Scan
[a_b_c_include_d_index].[test]
Cost: 89%
ここで、Group byを次のように変更すると、
GROUP BY a, b, c
WITH ROLLUP
それは違いを生み、異なる実行プランを生成します(もちろん異なる結果セットを生成します)。ただし、少なくともそのSQL-Fiddleテストでは、引き続きインデックスを使用します。順序が一致しない場合、インデックスからデータを取得しますが、(ロールアップ値を計算するために)中間ソートを実行する必要があります。
はい、それらの列をカバーするインデックスがある場合。
MSDNのドキュメント によると:
複数列インデックスのコンテキストでは、ORDER-BYまたはGROUP-BYが特定のインデックスを考慮するために、ORDER-BYまたはGROUP-BY列は、インデックス列のプレフィックスセットと正確な順序で一致する必要があります。たとえば、インデックス
CREATE INDEX Emp_Name ON Employees ("Last Name" ASC, "First Name" ASC)
次のクエリを最適化するのに役立ちます。
... ORDER BY / GROUP BY "Last Name" ...
... ORDER BY / GROUP BY "Last Name", "First Name" ...
それは最適化に役立ちません:
... ORDER BY / GROUP BY "First Name" ...
... ORDER BY / GROUP BY "First Name", "Last Name" ...