更改 GROUP BY 中列的顺序会影响性能吗?

sha*_*oth 7 performance sql-server azure-sql-database query-performance

我有一个这样的 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)
Run Code Online (Sandbox Code Playgroud)

在庞大的数据集上,实际执行计划大部分时间都归因于对应于逻辑操作 Aggregate物理操作 HashMatch 的节点

更改列和条件在列表中的GROUP BY列出顺序会影响性能吗?

ype*_*eᵀᴹ 7

不管 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
Run Code Online (Sandbox Code Playgroud)

查询:

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 ;
Run Code Online (Sandbox Code Playgroud)

生成相同的执行计划:

执行计划

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%
Run Code Online (Sandbox Code Playgroud)

现在,如果您将该组更改为:

    GROUP BY a, b, c
      WITH ROLLUP
Run Code Online (Sandbox Code Playgroud)

它确实有所作为,并且确实会产生不同的执行计划(当然还有不同的结果集)。尽管如此,它仍然使用索引,至少在那个 SQL-Fiddle 测试中是这样。在顺序不匹配的情况下,它从索引中获取数据,但必须进行中间排序(以计算汇总值)。


Jas*_*son 2

是的,如果您有一个涵盖这些列的索引。

根据MSDN 上的文档

在多列索引的上下文中,为了使 ORDER-BY 或 GROUP-BY 考虑特定索引,ORDER-BY 或 GROUP-BY 列必须与索引列的前缀集匹配并具有准确的顺序。例如,索引

CREATE INDEX Emp_Name ON Employees ("Last Name" ASC, "First Name" ASC) 
Run Code Online (Sandbox Code Playgroud)

可以帮助优化以下查询:

... ORDER BY / GROUP BY "Last Name" ...
... ORDER BY / GROUP BY "Last Name", "First Name" ...
Run Code Online (Sandbox Code Playgroud)

它无助于优化:

... ORDER BY / GROUP BY "First Name" ...
... ORDER BY / GROUP BY "First Name", "Last Name" ...
Run Code Online (Sandbox Code Playgroud)

  • `GROUP BY "First Name", "Last Name"` 与 `GROUP BY "Last Name", "First Name"` 相同,不是吗?因此,根据 WHERE 和 ON,顺序并不重要。对于 ORDER BY 来说,确实如此 (2认同)