
MySQL 聚合函数初探
MySQL 提供了许多聚合函数,常见的如sum,avg,count,min,max等。
那这些聚合函数在MySQL 底层是怎么实现的?
聚合函数(Aggregate Function)实现的大部分代码在item_sum.h和item_sum.cc。
聚合函数在代码中具体的枚举如下:
本文以下列示例来讲解:
聚合函数的类设计大概如下
由上图可以发现MySQL 聚合函数实现是把distinct逻辑抽离出来,变成了aggregator_distinct和aggregator_simple,
服务于继承了Item_sum的所有聚合类。(当然Item_sum本身是继承于Item)
上面是2个类的部分代码,由此我们发现 Aggregator_simple
基本只是个调用wrap,表示非distinct的Item_sum处理,
直接调用的是聚合类的逻辑。
在 MySQL 中要实现聚合函数要有3个重要的步骤:setup, add, endup。
- setup 在处理之前初始化
- add 表示每条记录的处理
- endup 收尾后最后计算聚合的结果。
回到代码
setup 阶段
(Aggregator_distinct::setup 截取部分代码)
由上知 setup 阶段主要做的是创建临时表和 tree ,设置比较函数。
add 阶段
(Aggregator_distinct::add 截取部分代码)
这边看到当 tree 存在时,MySQL 把记录加入 tree (实际为红黑树)中来去重复。
如果tree不存在,就用临时表来持久存储。在 ha_write_row 写入临时表之前会 check_unique_constraint 去重。
而 tree 和临时表就是 setup 阶段所创建的。setup 的 tree 是存在,什么时候销毁了呢。看下面:
可以看到MySQL 的策略是维护一颗红黑树这样的数据结构来去重。
当tree的数量过大时,内存放不下,就会flush到磁盘上,采用临时表来持久化,同时销毁tree。
endup 阶段
可以看到最后取结果的时候
如果 tree 存在而且在内存中,直接取 tree 的节点个数。
如果 tree 不存在就取临时表的行数。
文章转载自公众号:GreatSQL社区
