聚合(分组)如何在SQL Server上工作?
SQL Server如何实现group by子句(聚合)?
作为灵感,采取this question’s查询的执行计划: select p_id,DATEDIFF(D,MIN(TreatmentDate),MAX(TreatmentDate)) from patientsTable group by p_id 在查询数据之前,简单的select语句及其执行计划是这样的: 使用查询和执行计划检索数据后:
通常它是Stream Aggregate或Hash Aggregate.
> Stream aggregate对结果集进行排序,扫描并返回每个新值(不等于扫描中的最后一个值).它允许保留一组聚合状态变量. 让我们看看AVG是如何工作的.它需要两个状态变量:sum和count grouper value 1 4 1 3 2 8 1 7 2 1 1 2 2 6 2 3 流聚合 >首先,它需要对值进行排序: grouper value 1 4 1 3 1 7 1 2 2 8 2 1 2 6 2 3 >然后,它保留一组状态变量,初始化为0,并扫描排序的结果集: 石斑鱼价值总和 哈希聚合 >只需扫描值并将状态变量保留在哈希表中: grouper value -- Hash miss. Adding new entry to the hash table -- [1] (0,0) -- ... and updating it: 1 4 [1] (4,1) -- Hash hit. Updating the entry: 1 3 [1] (7,2) -- Hash miss. Adding new entry to the hash table -- [1] (7,2) [2] (0,0) -- ... and updating it: 2 8 [1] (7,2) [2] (8,1) 1 7 [1] (14,3) [2] (8,1) 2 1 [1] (14,3) [2] (9,2) 1 2 [1] (16,4) [2] (9,2) 2 6 [1] (16,4) [2] (15,3) 2 3 [1] (16,4) [2] (18,4) -- Scanning the hash table and returning the aggregated values -- 1 4 -- 2 4.5 通常,如果结果集已经排序,则排序更快(例如,值来自索引或由前一操作排序的结果集). 散列更快是结果集未排序(散列比排序更快). MIN和MAX是特殊情况,因为它们不需要扫描整个组:只有组内聚合列的第一个和最后一个值. 不幸的是,与大多数其他系统不同,SQL Server无法有效利用它,因为它不适合进行INDEX SKIP SCAN(跳过不同的索引键). 虽然简单的MAX和MIN(没有GROUP BY子句)如果聚合列上的索引存在,则使用TOP方法,而带有GROUP BY的MIN和MAX使用与其他聚合函数相同的方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |