SQL调优指南—SQL调优进阶—聚合优化和执行

简介: 本文介绍如何优化器和执行器如何处理聚合(Group-by),以达到减少数据传输量和提高执行效率的效果。

基本概念

聚合操作(Aggregate,简称Agg)语义为按照GROUP BY指定列对输入数据进行聚合的计算,或者不分组、对所有数据进行聚合的计算。PolarDB-X支持如下聚合函数:

  • COUNT
  • SUM
  • AVG
  • MAX
  • MIN
  • BIT_OR
  • BIT_XOR
  • GROUP_CONCAT

聚合(Agg)

本文介绍均为不下推的Agg的实现。如果已被下推到LogicalView中,则由存储层MySQL来选择执行方式,聚合(Agg)由两种主要的算子HashAgg和SortAgg实现。

HashAgg

HashAgg利用哈希表实现聚合:

  1. 根据输入行的分组列的值,通过Hash找到对应的分组。
  2. 按照指定的聚合函数,对该行进行聚合计算。
  3. 重复以上步骤直到处理完所有的输入行,最后输出聚合结果。


> explain select count(*) from t1 join t2 on t1.id = t2.id group by t1.name,t2.name;
Project(count(*)="count(*)")
  HashAgg(group="name,name0", count(*)="COUNT()")
    BKAJoin(condition="id = id", type="inner")
      Gather(concurrent=true)
        LogicalView(tables="t1", shardCount=2, sql="SELECT `id`, `name` FROM `t1` AS `t1`")
      Gather(concurrent=true)
        LogicalView(tables="t2_[0-3]", shardCount=4, sql="SELECT `id`, `name` FROM `t2` AS `t2` WHERE (`id` IN ('?'))")

Explain结果中,HashAgg算子还包含以下关键信息:

  • group:表示GROUP BY字段,示例中为name,name0分别引用t1,t2表的name列,当存在相同别名会通过后缀数字区分 。
  • 聚合函数:等号(=) 前为聚合函数对应的输出列名,其后为对应的计算方法。示例中 count(*)="COUNT()" ,第一个 count(*) 对应输出的列名,随后的COUNT()表示对其输入数据进行计数。

HashAgg对应可以通过Hint来关闭:/*+TDDL:cmd_extra(ENABLE_HASH_AGG=false)*/

SortAgg

SortAgg在输入数据已按分组列排序的情况,对各个分组依次完成聚合。

  • 保证输入按指定的分组列排序(例如,可能会看到 MergeSort 或 MemSort)。
  • 逐行读入输入数据,如果分组与当前分组相同,则对其进行聚合计算。
  • 如果分组与当前分组不同,则输出当前分组上的聚合结果。

相比 HashAgg,SortAgg 每次只要处理一个分组,内存消耗很小;相对的,HashAgg 需要把所有分组存储在内存中,需要消耗较多的内存。


> explain select count(*) from t1 join t2 on t1.id = t2.id group by t1.name,t2.name order by t1.name, t2.name;

Project(count()="count()")
MemSort(sort="name ASC,name0 ASC")
HashAgg(group="name,name0", count(*)="COUNT()")
BKAJoin(condition="id = id", type="inner")
Gather(concurrent=true)
LogicalView(tables="t1", shardCount=2, sql="SELECT `id`, `name` FROM `t1` AS `t1`")
Gather(concurrent=true)
LogicalView(tables="t2_[0-3]", shardCount=4, sql="SELECT `id`, `name` FROM `t2` AS `t2` WHERE (`id` IN ('?'))")

SortAgg对应可以通过Hint来关闭:/+TDDL:cmd_extra(ENABLE_SORT_AGG=false)/

两阶段聚合优化

两阶段聚合,即通过将Agg拆分为部分聚合(Partial Agg)和最终聚合(Final Agg)的两个阶段,先对部分结果集做聚合,然后将这些部分聚合结果汇总,得到整体聚合的结果。

如下示例的SQL中,HashAgg 中拆分出的部分聚合(PartialAgg)会被下推至MySQL上的各个分表,而其中的AVG函数也被拆分成 SUM和 COUNT 以实现两阶段的计算:


> explain select avg(age) from t2 group by name
Project(avg(age)="sum_pushed_sum / sum_pushed_count")
HashAgg(group="name", sum_pushed_sum="SUM(pushed_sum)", sum_pushed_count="SUM(pushed_count)")
Gather(concurrent=true)
LogicalView(tables="t2_[0-3]", shardCount=4, sql="SELECT `name`, SUM(`age`) AS `pushed_sum`, COUNT(`age`) AS `pushed_count` FROM `t2` AS `t2` GROUP BY `name`")

两阶段聚合的优化能大大减少数据传输量、提高执行效率。

总的来说,大部分场景做聚合的时候都倾向于选择HashAgg,只要当以下场景下才适合选择SortAgg做聚合:

  1. 数据比较多,内存严重不足。
  2. 聚合算子的输入已经按照Group By 列做好排序,这样做SortAgg就不需要额外排序,执行效率会更高。
  3. 当数据有严重倾斜,导致HashAgg执行效率不高,优先使用SortAgg
相关文章
宜搭小技巧|自动计算日期时长,3个公式帮你搞定!
使用「时间函数」实现日期时长自动计算功能,让表单填写更轻松。
2433 0
宜搭小技巧|自动计算日期时长,3个公式帮你搞定!
PHP:ThinkPHP5.0视图View模板语法
PHP:ThinkPHP5.0视图View模板语法
400 0
PHP:ThinkPHP5.0视图View模板语法
|
小程序 数据管理 大数据
《数字化与碳中和(园区篇)》报告正式发布,助力加快推进国家“双碳”战略实施
2022年9月3日,由阿里云与施耐德联合信通院、工信部国际合作中心等单位共同编制的《数字化与碳中和(园区篇)》正式发布。报告基于实地调研及各单位实践经验,深入分析双碳园区发展现状及面临形式,提出从OT到IT进行服务能力整合的思路,制定“园区管理端、企业应用端、生态服务端”三端协同的园区碳中和服务平台解决方案,阐述碳中和服务平台的总体架构、核心场景以及建设运营等内容,并分享不同类型园区的实践案例。该报告为园区管理者、建设者、运营方以及相关入住企业提供了有价值的参考,助力加快推进国家“双碳”战略实施。
《数字化与碳中和(园区篇)》报告正式发布,助力加快推进国家“双碳”战略实施
|
Web App开发 tengine 编解码
通过ffplay播放OSS上的mp3文件会断开
抽丝剥茧定位一个疑难问题。
988 1
|
存储 Kubernetes IDE
云端开发是个坑!4 年后,我们又回到了本地环境
云端开发环境是软件工程的未来吗?
598 0
云端开发是个坑!4 年后,我们又回到了本地环境
【约束布局】ConstraintLayout 之 Chains 链式约束 ( Chains 简介 | 代码 及 布局分析 | 链头设置 | 间距设置 | 风格设置 | 权重设置 )(三)
【约束布局】ConstraintLayout 之 Chains 链式约束 ( Chains 简介 | 代码 及 布局分析 | 链头设置 | 间距设置 | 风格设置 | 权重设置 )(三)
502 0
【约束布局】ConstraintLayout 之 Chains 链式约束 ( Chains 简介 | 代码 及 布局分析 | 链头设置 | 间距设置 | 风格设置 | 权重设置 )(三)
|
安全 Java BI
看山聊Java:一文掌握 Java8 Stream 中 Collectors 的 24 个操作
Java8 应该算是业界主版本了,版本中重要性很高的一个更新是Stream流处理。关于流处理内容比较多,本文主要是说一下Stream中的Collectors工具类的使用。
498 0
看山聊Java:一文掌握 Java8 Stream 中 Collectors 的 24 个操作
|
自然语言处理 数据可视化 前端开发
电商搜索“无结果率高,体验差”怎么办?
本文针对电商搜索中遇到的“搜索无结果,排序机制不满足业务需求”的问题进行刨析,并通过阿里云开放搜索的最佳实践跟大家聊一聊应该如何应对解决~
3262 0
电商搜索“无结果率高,体验差”怎么办?
|
域名解析 关系型数据库 MySQL
基于阿里云服务器使用宝塔面板搭建Typecho博客网站
Typecho是一款基于PHP的国内开源博客系统,用户可以使用Typecho快速搭建个人博客。 最近把个人网站重置一下,所以记录一下这个过程。 个人网站地址:http://www.eknown.cn 下面进入博客搭建: 准备:服务器一台 Typecho官网:http://typecho.org 主要步骤: 购买服务器、安装宝塔面板 提前备案域名,或者直接使用服务器IP地址访问 安装和配置Typecho 一、配置宝塔面板 首先在服务器安装宝塔面板,我使用的是阿里云轻量级服务器,安装系统时选择了宝塔镜像。
3188 0
|
存储 SQL 机器学习/深度学习
MITRE ATT&CK 框架“入坑”指南
MITRE ATT&CK 框架是打造检测与响应项目的流行框架。这玩意有没有用不确定,但是你绝对承担不起不会用的风险。
MITRE ATT&CK 框架“入坑”指南