为什么使用 GROUP BY 子句的聚合查询比不使用 GROUP BY 子句要快得多?

Rac*_*hel 12 performance sql-server-2005 aggregate parallelism query-performance

我只是很好奇为什么聚合查询使用GROUP BY子句比没有子句运行得更快。

例如,这个查询需要将近 10 秒才能运行

SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
Run Code Online (Sandbox Code Playgroud)

虽然这个只需不到一秒钟

SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
GROUP BY CreatedDate
Run Code Online (Sandbox Code Playgroud)

CreatedDate在这种情况下只有一个,因此分组查询返回与未分组查询相同的结果。

我注意到两个查询的执行计划是不同的 - 第二个查询使用 Parallelism 而第一个查询没有。

Query1 执行计划 Query2 执行计划

如果 SQL Server 没有 GROUP BY 子句,它以不同的方式评估聚合查询是否正常?在不使用GROUP BY子句的情况下,我可以做些什么来提高第一个查询的性能?

编辑

我刚刚了解到我可以使用OPTION(querytraceon 8649)将并行性的开销开销设置为 0,这使得查询使用一些并行性并将运行时间减少到 2 秒,尽管我不知道使用此查询提示是否有任何缺点。

SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
OPTION(querytraceon 8649)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

我仍然更喜欢较短的运行时间,因为查询旨在根据用户选择填充一个值,因此理想情况下应该像分组查询一样是即时的。现在我只是结束我的查询,但我知道这并不是一个理想的解决方案。

SELECT Min(CreatedDate)
FROM
(
    SELECT Min(CreatedDate) as CreatedDate
    FROM MyTable WITH (NOLOCK) 
    WHERE SomeIndexedValue = 1
    GROUP BY CreatedDate
) as T
Run Code Online (Sandbox Code Playgroud)

编辑 #2

回应Martin 要求提供更多信息的请求

无论CreatedDateSomeIndexedValue对他们有独立的非唯一,非聚集索引。SomeIndexedValue实际上是一个 varchar(7) 字段,即使它存储一个指向另一个表的 PK (int) 的数值。数据库中没有定义两个表之间的关系。我根本不应该更改数据库,并且只能编写查询数据的查询。

MyTable包含超过 300 万条记录,每条记录都被分配到一个它所属的组 ( SomeIndexedValue)。组可以是 1 到 200,000 条记录

Mar*_*ith 8

看起来它可能CreatedDate按照从低到高的顺序跟踪索引并进行查找以评估SomeIndexedValue = 1谓词。

当它找到第一个匹配的行时,它就完成了,但是在找到这样的行之前,它可能会进行比预期更多的查找(它假设与谓词匹配的行是根据日期随机分布的。)

有关类似问题,请在此处查看我的答案

此查询的理想索引是 one on SomeIndexedValue, CreatedDate。假设您不能添加或至少将您现有的SomeIndexedValue封面索引CreatedDate作为包含列,那么您可以尝试按如下方式重写查询

SELECT MIN(DATEADD(DAY, 0, CreatedDate)) AS CreatedDate
FROM MyTable
WHERE SomeIndexedValue = 1
Run Code Online (Sandbox Code Playgroud)

以防止它使用该特定计划。