zoukankan      html  css  js  c++  java
  • SQL Server 2005技术内幕:查询、调整和优化4——聚合

    对于聚合,SQL Server支持两种物理操作符:流聚合与哈希聚合。

    标量聚合

    标量聚合通过在选择列表中没有GROUP BY语句的聚合函数查询。标量聚合总是返回一个单一的行。SQL Server总是使用流聚合操作符实现标量聚合。

    下面是个简单的例子:

     

    select COUNT(*from [Orders]

     

    这个查询产生下面的计划:

    流聚合操作符就是计算输入行的大小并返回结果。流聚合实际计算Bigint的总数([Expro1004])。计算的数量需要把这个结果转换成期待的Int型。注意到标量流聚合是一个没有页节点操作符例子中的一个,可以在空输入集时产生一个输入。

     

    如何实现其他的简单标量聚合函数,例如MINMAXSUM。一个单一流聚合操作符可以在同一时刻计算多个标量聚合。

     

    select MIN(Orderdate), MAX(orderdate) from [Orders]

     

    下面是使用单一流聚合操作符的查询计划:

    注意到SQL Server不需要对MINMAX集合转换结果,因为这些集合是基于订单日期列数据类型计算的。

    一些集合,例如AVG实际上是从其他两个集合如SUMCOUNT中计算的:

     

    select AVG(Freight) from [orders]

     

    请注意计划中的计算标量操作符是如何从sumcount中计算平均值的:

     

    CASE表达式是必须的,用以确定SQL Server不会试图被零整除。

            

    select SUM(Freight) from [orders]

            

       尽管本质上SUM不需要计算,但仍然要进行计数:

             以下这个查询计划中的CASE表达式如果应用COUNT来确保SUM在没有行时返回NULL,而不是零。

     

    Scalar Distinct

             如果对标量聚合添加DISTINCT关键字进行查询,计算以运送的订单的不同城市的数量,查询如下:

     

    select COUNT(distinct [shipcity]from [orders]

    以上查询产生的查询计划如下:

    因为查询必须对那些ShipCity列上有唯一值的行计算,SQL Server 增加显示排序操作符消除ShipCity上的重复值,显示排序是SQL Server用来消除排序重复行的常见方法之一。在对输入集进行排序后就很容易去除重复的行,因为重复的行和另外一个行是邻接的。

     

    多个 Distinct

    select COUNT(distinct [shipaddress]), COUNT(distinct[shipcity]

       
    from [orders]

     

    SQL Server可以通过消除ShipAddress列上重复值的行来计算COUNTDISTINCT[ShipAddress])。类似的,SQL Server可以通过消除ShipCity列上的重复值来计算COUNTDISTINCT[ShipTity])。但是,假设给出的这两个行的集合不同,SQL Server如果同时对这两个行进行计算,SQL Server做不到,它必须先计算一个聚合的结果,然后计算另一个,再把这两个结果合并成一个单一的输出:

     

    嵌套循环连接的两个输入从原始的查询中计算两个数量,其中一个输入去掉重复的,计算ShipAddress列的数量,另一个输入去掉重复的,计算ShipCity列的数量。嵌套循环连接没有连接谓词,它是交叉连接。因为嵌套循环连接的两个输入每一个产生单一的行,且它们的标量集合-交叉连接的结果也会一个单一的行。交叉连接就是把结果的两行“粘贴”为单一的行。

     

    流聚合

     

    算法         流聚合依赖与获得存储在GROUP BY列中的数据。如同合并连接,如果一个查询包含GROUP BY语句多于一行,流聚合会使用任何包含所有行的排序次序。例如,流聚合会对Col1列和Col2列分组,而数据存储在(Col1Col2)或(Col2Col1)上。与合并连接类似,排序次序也会被一个索引或一个显示排序操作符影响。排序次序将确保列GROUP BY有着相同值的行集合彼此相连。

    例如,为了计算SUM,流聚合会考虑每个输入行。如果输入行属于目前的组(输入行的group by列和以前行的group by列是匹配的),则流聚合可通过从输入行中增加合适的值来更新目前的SUM。如果输入的行属于一个新的组(输入的行group by列和以前行的group by列不匹配),流聚合会输出目前的SUM,把SUM设为零,开始新的组。

    简单示例  下面的查询将计算对于每个地址运送订单的数量:

    select [ShipAddress][ShipCity]COUNT(*)

    From [Orders] group by [ShipAddress][ShipCity]

     

    下面是这个查询的计划:

     

    除了SQL Server在聚合前需要对数据排序外,这个计划和之前看到的标量聚合的查询基础一样,可以认为标量聚合是一个包含所有行的一个大组,因此,对于一个标量聚合,没有必要将行排序为不同的组。(未完待续)

  • 相关阅读:
    PHP 使用 ElasticSearch
    PHP面试题目
    MySQL取得某一范围随机数
    Git版本控制的基本命令
    PHP中array_merge和array相加的区别分析
    nginx服务器常见错误代码500、501、502、503、504、505
    Laravel小项目之第4节 Laravel-通过表单实现新增及操作状态提示功能
    前端基础 jQuery
    前端基础 DOM & BOM
    前端基础 & 初识JS(JavaScript)
  • 原文地址:https://www.cnblogs.com/fengxiang/p/1816078.html
Copyright © 2011-2022 走看看