MySQL 聚合函数初探

【MySQL】聚合函数和分组聚合 介绍聚合函数和分组聚合 阅读详情
  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
  • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
  • 作者:Q

MySQL 提供了许多聚合函数,常见的如sum,avg,count,min,max等。 那这些聚合函数在MySQL 底层是怎么实现的? 聚合函数(Aggregate Function)实现的大部分代码在item_sum.h和item_sum.cc。 聚合函数在代码中具体的枚举如下:

enum Sumfunctype {
    COUNT_FUNC,           // COUNT
    COUNT_DISTINCT_FUNC,  // COUNT (DISTINCT)
    SUM_FUNC,             // SUM
    SUM_DISTINCT_FUNC,    // SUM (DISTINCT)
    AVG_FUNC,             // AVG
    AVG_DISTINCT_FUNC,    // AVG (DISTINCT)
    MIN_FUNC,             // MIN
    MAX_FUNC,             // MAX
    STD_FUNC,             // STD/STDDEV/STDDEV_POP
    VARIANCE_FUNC,        // VARIANCE/VAR_POP and VAR_SAMP
    SUM_BIT_FUNC,         // BIT_AND, BIT_OR and BIT_XOR
    UDF_SUM_FUNC,         // user defined functions
    GROUP_CONCAT_FUNC,    // GROUP_CONCAT
    JSON_AGG_FUNC,        // JSON_ARRAYAGG and JSON_OBJECTAGG
    ROW_NUMBER_FUNC,      // Window functions
    RANK_FUNC,
    DENSE_RANK_FUNC,
    CUME_DIST_FUNC,
    PERCENT_RANK_FUNC,
    NTILE_FUNC,
    LEAD_LAG_FUNC,
    FIRST_LAST_VALUE_FUNC,
    NTH_VALUE_FUNC,
    ROLLUP_SUM_SWITCHER_FUNC,
    GEOMETRY_AGGREGATE_FUNC
  };

本文以下列示例来讲解:

CREATE TABLE test_agg (c1 int NULL)

INSERT into test_agg values(1),(2),(3),(3),(4),(4),(5),(5),(5);

SELECT count(DISTINCT c1) from test_agg;

聚合函数的类设计大概如下

图片

由上图可以发现MySQL 聚合函数实现是把distinct逻辑抽离出来,变成了aggregator_distinct和aggregator_simple,

服务于继承了Item_sum的所有聚合类。(当然Item_sum本身是继承于Item)

class Aggregator_simple : public Aggregator {
 public:
  Aggregator_simple(Item_sum *sum) : Aggregator(sum) {}
  Aggregator_type Aggrtype() override { return Aggregator::SIMPLE_AGGREGATOR; }
  bool setup(THD *thd) override { return item_sum->setup(thd); }
  void clear() override { item_sum->clear(); }
  bool add() override { return item_sum->add(); }
  void endup() override {}
};
class Aggregator_distinct : public Aggregator {
 public:
  ~Aggregator_distinct() override;
  Aggregator_type Aggrtype() override { return DISTINCT_AGGREGATOR; }

  bool setup(THD *) override;
  void clear() override;
  bool add() override;
  void endup() override;
};

上面是2个类的部分代码,由此我们发现 Aggregator_simple 基本只是个调用wrap,表示非distinct的Item_sum处理,

直接调用的是聚合类的逻辑。

在 MySQL 中要实现聚合函数要有3个重要的步骤:setup, add, endup。

  • setup 在处理之前初始化
  • add 表示每条记录的处理
  • endup 收尾后最后计算聚合的结果。

回到代码

setup 阶段

(Aggregator_distinct::setup 截取部分代码)

if (!(table = create_tmp_table(thd, tmp_table_param, list, nullptr, true,
                                   false, query_block->active_options(),
                                   HA_POS_ERROR, "")))
if (all_binary) {
        cmp_arg = (void *)&tree_key_length;
        compare_key = simple_raw_key_cmp;
} else {
    if (table->s->fields == 1) {
        compare_key = simple_str_key_cmp;
        cmp_arg = (void *)table->field[0];
    } else {
        uint32 *length;
        compare_key = composite_key_cmp;
        ....
     }
  }
 tree = new (thd->mem_root) Unique(compare_key, cmp_arg, tree_key_length,
          item_sum->ram_limitation(thd));
 if (!tree) return true;

由上知 setup 阶段主要做的是创建临时表和 tree ,设置比较函数。

add 阶段

(Aggregator_distinct::add 截取部分代码)

if (tree) {
      return tree->unique_add(table->record[0] + table->s->null_bytes);
    }
    if (!check_unique_constraint(table)) return false;
    if ((error = table->file->ha_write_row(table->record[0])) &&
        !table->file->is_ignorable_error(error))

这边看到当 tree 存在时,MySQL 把记录加入 tree (实际为红黑树)中来去重复。

如果tree不存在,就用临时表来持久存储。在 ha_write_row 写入临时表之前会 check_unique_constraint 去重。

而 tree 和临时表就是 setup 阶段所创建的。setup 的 tree 是存在,什么时候销毁了呢。看下面:

inline bool unique_add(void *ptr) {
    DBUG_TRACE;
    DBUG_PRINT("info", ("tree %u - %lu", tree.elements_in_tree, max_elements));
    if (tree.elements_in_tree > max_elements && flush()) return true;
    return !tree_insert(&tree, ptr, 0, tree.custom_arg);
  }
bool Unique::flush() {
  Merge_chunk file_ptr;
  elements += tree.elements_in_tree;
  file_ptr.set_rowcount(tree.elements_in_tree);
  file_ptr.set_file_position(my_b_tell(&file));
  if (tree_walk(&tree, unique_write_to_file, this, left_root_right) ||
      file_ptrs.push_back(file_ptr))
    return true; /* purecov: inspected */
  delete_tree(&tree);
  return false;
}

可以看到MySQL 的策略是维护一颗红黑树这样的数据结构来去重。

当tree的数量过大时,内存放不下,就会flush到磁盘上,采用临时表来持久化,同时销毁tree。

endup 阶段
if (tree && tree->is_in_memory()) {
      sum->count = (longlong)tree->elements_in_tree();
      endup_done = true;
    }
    if (!tree) {
      table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
      if (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT)
        sum->count = table->file->stats.records;
      else {
        if (table->file->inited) table->file->ha_index_or_rnd_end();
        ha_rows num_rows = 0;
        table->file->ha_records(&num_rows);
        if (table->hash_field) table->file->ha_index_init(0, false);
        sum->count = static_cast<longlong>(num_rows);
      }
      endup_done = true;
    }

可以看到最后取结果的时候

如果 tree 存在而且在内存中,直接取 tree 的节点个数。

如果 tree 不存在就取临时表的行数。


Enjoy GreatSQL :)

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

捉虫活动详情:https://greatsql.cn/thread-97-1-1.html

社区博客有奖征稿详情:https://greatsql.cn/thread-100-1-1.html

6440

MySQL 08章——聚合函数 阅读详情

相关推荐

MySQL DISTINCT 的基本实现原理详解

主要介绍了MySQL DISTINCT 的基本实现原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

MySQL数据库 实验报告(一)

MySQL数据库 实验报告(一) 1、实验目的 (1)掌握系统数据类型的特点和功能 (2)掌握创建、修改表结构的方法 (3)掌握数据添加的方法 2、实验预习与准备 (1)MYSQL中创建数据库的命令 (2)表结构的创建、修改和删除 (3)MYSQL导入导出表数据的方式 (4)添加数据的SQL命令 3、实验内容及步骤 (1)利用SQL命令创建名为“jwgl”+“自己学号”的数据库 (2)使用命令行方式利用SQL语句在第一步创建的数据库中按下列要求创建数据表 a)创建如下表所示的student表(学生表) 列名

gxy3202365628的博客 5万+

TwinCAT报SSE invalid operation错误

错误类型 TwinCAT程序中报出以下错误: 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 **** 383 ms | 'Port_851' (851): Exception (Exception Code: 0xc0000090, SSE invalid operation) in PLC Application Untitled1 Instance, Task PlcTask (RBP: 0xffffb3016c80ecc0, RIP: 0xffffe708ee5b5f53, RSP:

akadiao的博客 4161

MySQL专题四——MySQL函数(聚合函数)

MySQL聚合函数 1.聚合函数介绍 什么是聚合函数 聚合函数作用于一组数据,并对一组数据返回一个值 聚合函数类型 AVG() SUM() MAX() MIN() COUNT() 聚合函数语法 SELECT [column,] group function(column), ... FROM table [WHERE condition] [GROUP BY column] [ORDER BY column]; 1.1 AVG和SUM函数 可以对**数值型数据**使用AVG和SUM

qq_24292711的博客 2070

Windows 10 本地开发环境:用 ShardingSphere-Proxy 5.4.1 快速搭建 MySQL 分库分表测试环境

本文详细介绍了在Windows 10系统中使用ShardingSphere-Proxy 5.4.1快速搭建MySQL分库分表测试环境的完整教程。从环境准备、MySQL配置到ShardingSphere-Proxy的核心设置,逐步指导开发者完成本地开发环境的搭建,并提供了分片策略详解和常见问题排查方法,帮助开发者高效验证分库分表功能。

weixin_28366053的博客 214

数据分析面试八股文--技能软件类

数据分析的“三板斧"指的是三个在 Python 数据分析领域广泛使用的库:NumPy,Pandas,和 Matplotlib。这三个库提供了处理和分析数据的强大工具。NumPyNumPy(Numerical Python)是一个开源 Python 库,用于支持大型多维数组和矩阵运算。此外,NumPy 还提供了大量的数学函数来操作这些数组。np.array():创建数组np.arange():返回一个有终点和起点的固定步长的排列。

zfyzfw的博客 4377

mysql distinct多条件去重逻辑

distinct 多个字段 例a select distinct a , b , c from test_table 例b select distinct a from test_table 之间区别 例a会选择唯一的一行,例b选择唯一列。 前一种只要三个字段都不重复就取出来。后面只取唯一的 a 字段; select distinct a , b , c from test_ta...

weixin_43069769的博客 7161

2. Netty使用JSerialComm进行串口读取(二)

现在开始处理这些问题 第一个问题:串口读取超时异常一路传播到最后也没有处理。 ​ 第二个问题:即使处理了该异常,程序仍然退出,这不能满足一些实际使用要求需求。该问题与设置很长的读取超时时间没关系,无论多长到时间后总会退出。

s3c2410的博客 2461

MySQL之聚合函数的应用

聚合函数是SQL中实现数据统计分析的核心工具,通过`COUNT`、`SUM`、`AVG`、`MAX`、`MIN`的灵活组合,我们可以从海量数据中快速提取关键业务指标。在实际应用中,需注意以下几点:1. 场景匹配:根据业务需求选择合适的聚合函数,如计数用`COUNT`,求和用`SUM`2. 分组逻辑:合理使用`GROUP BY`和`HAVING`,实现精细化分组统计3. 性能优化:利用索引、避免函数计算、分步骤处理大数据量聚合4. NULL处理:显式处理NULL值,确保统计结果符合业务逻辑。

2302_76852954的博客 1132

Unity-Mirror网络框架-从入门到精通之MultipleMatches示例

Multiple Matches 示例主要讲述了如何在使用 Mirror 网路框架时管理多个游戏匹配。以及如何设置一个能够同时支持多个游戏会话的系统,使玩家能够加入他们所选择的比赛,而不是强制他们加入一个单一的匹配。

TxNet 964

innovus:NRDB-2276 special net route layer与NanoRouteMode route layer冲突问题解决方法

NanoRouteMode中设置绕线层次2-6,但是被动到的special net有8-11的preferred route layer,这个层次可能是create_route_type+set_ccopt_property -net_type 定义的。二者绕线层次范围有冲突,导致在调整过这条net后再绕线就会提示失败。然后再下route_design 等route命令去绕别的net。我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?

m0_61544122的博客 1101

MySQL Distinct 相关源码阅读笔记

Based on MySQL 8.0 community version Aggregator_distinct 指聚合型DISTINCT,下面为一些example: SELECT COUNT(DISTINCT) -- 除了COUNT外,MySQL目前agg DISTINTCT只支持数值类型 SELECT SUM(DISTINCT) SELECT AVG(DISTINCT) 以前的版本dist...

weixin_30532759的博客 273

GeoServer改造Springboot源码一(公共部分)

今天开始开启关于GeoServer的一个全新系列,主要是把改造Springboot后的详细代码粘贴出来,此文应配合《》系列共同阅读,按照前系列的时间顺序结合此系列的源码展示可以快速构建GeoServer功能的二次封装的后端系统。

龙井的专栏 1902

mysql聚合函数总结

1.首先我们需要了解下什么是聚合函数 聚合函数aggregation function又称为组函数。 认情况下 聚合函数会对当前所在表当做一个组进行统计。 2.聚合函数的特点 (1).每个组函数接收一个参数(字段名或者表达式) 统计结果中默认忽略字段为NULL的记录 (2).要想列值为NULL的行也参与组函数的计算,必须使用IFNULL函数对NULL值做转换。 (3).不允许出现嵌套 比如sum(max(xx)) 3.聚合函数 count(),求数据表的行数 select count(*/字段名) from

w1194890394的博客 7660

在lio_sam中融入GPS

在LIO(激光惯性里程计)系统中,将GPS信息融合到里程计中,借助GTSAM(Georgia Tech Smoothing and Mapping)库进行因子图优化,可以有效提升全局定位精度。当进入到GPS信号不好或缺失的环境中,需要借助融合后的里程计反算经纬度,来获取高精度的定位信息。利用GeographicLib第三方库将经纬度投影到局部笛卡尔坐标系中。

如果想成为中心,那么就到中心去吧。 1211

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

MySQL——聚合函数和group by分组的使用

文章目录MySQL——聚合函数和group by分组的使用1、聚合函数介绍2、GROUP BY 分组3、常见的聚合函数4、SQL执行顺序 MySQL——聚合函数和group by分组的使用 1、聚合函数介绍 SQL聚合函数计算一组数据的集合并返回单个值。 除 COUNT 以外,聚合函数忽略空值,如果COUNT函数的应用对象是一个确定列名,并且该列存在空值,此时COUNT仍会忽略空值。 因为聚合函数对一组值进行操作,所以它通常与SELECT语句的GROUP BY子句一起使用,以计算为每个分组提供信息的度量。

万里顾一程的博客 2万+

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【MySQL】聚合函数

介绍了五大常用聚合函数、GROUP BY、HAVING的使用方法,还有简单分析了一下SELECT语句的执行顺序

Decade0712的博客 1万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

MySQL中的聚合函数

文章目录五种常用的聚合函数什么是聚合函数AVG和SUM函数MIN和MAX函数COUNT函数有关COUNT的效率问题GROUP BY基本实现使用多个列分组GROUP BY中使用WITH ROLLUPHAVINGWHERE和HAVING的对比 五种常用的聚合函数 什么是聚合函数 聚合函数作用于一组数据,并对一组数据返回一个值。 聚合函数不能嵌套调用。比如不能出现类似“AVG(SUM(字段名称))”形式的调用。 AVG和SUM函数 AVG函数:求平均值 SUM函数:求总和 AVG / SUM :只适用于数

十八岁讨厌编程的博客 8699

mysql的所有聚合函数_MySQL 聚合函数(一)聚合(组合)函数概述

MySQL版本:5.7+一、MySQL 5.7中的聚合函数MySQL 5.7中的聚合函数如下:除非另有说明,否则组合函数会忽略NULL值。如果在不包含Group By子句的语句中使用组合函数,就等效于对所有行进行分组。(个人理解是,结果总是只有一行。)关于这点的更多信息,后面的小节“MySQL处理Group By的方式”会讲到。聚合函数中,方差和标准差函数会对数值参数返回DOUBLE值。SUM()...

weixin_29947319的博客 1万+

MySQL简单函数,聚合函数的使用

介绍了MySQL的字符串函数,数值函数,日期函数,流程函数,并复习了一下聚合函数

2202_76097976的博客 1600

MySQL之聚合函数

聚合函数作用于一组数据,并对一组数据返回一个值。

曦 1468

MySQL表聚合函数

聚合函数的介绍及使用!

终为nullptr 2942

Mysql梳理11——聚合函数

聚合函数作用于一组数据,并对一组数据返回一个值。

haozihua的博客 2432

mysql聚合函数---总体聚合、总体累加、分组聚合、分组累加

mysql因为没有窗口分析函数,所以分组累加需要构造sql语句来实现。 数据:select * from emp; 一、mysql总体聚合函数 min()、max()、count()、sum()、avg() select count(ename) ,max(sal),min(sal),sum(sal),round(avg(sal),2) from emp; 二、mysql...

Jalen big data analysis的博客 7764
上一篇: MySQL 8.0.30动态redo log初探
下一篇: MySQL科学计数法展示解惑
GreatSQL社区
博客等级 码龄5年 1210粉丝 390原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值