摘要:
对聚合的多线程并行化做概要设计
需求分析:
功能需求:
- 与现有逻辑处理的聚合条件保持一致
- 以Aggregate函数为入口, 以ResultSender为结果输出
性能需求:
表的数据量限制:
- 物理磁盘能容纳的上限
- 存在超出内存限制
内存占用限制:
- 添加参数控制聚合时候可使用的最大的内存
- 超出限制则用临时磁盘文件
执行耗时限制:
- 相同条件下,最多与innodb的聚合查询处于相同数量级
- 以小于innodb的聚合查询耗时为目标
概要功能细分:
表元组分割:
分割目标:
- 将单线程遍历的处理的表数据,均匀的分为不同的区间, 使不同的工作线程可以独立的处理某个区间的数据
- 正确处理不同的工作线程所面临的内存可见性, 确保工作线程本身功能的完整与正确,而不会由于临界区的重叠导致不同线程工作时互相影响
面临问题:
- 如何拿到表元组的描述信息, 一共多少行,多少列,有多少个pack?
- 将表元组分区间的规则是什么, 要启动多少个工作线程, 每个工作线程处理多少区间?
- GroupByWrapper当前保存了表的完整的信息, 并且持有列的某一行是否有数据的block的标识信息, 导致无法多线程并行处理该类。是否在每个线程都维护一个GroupByWrapper类只保存当前表元组区间的信息,以便于工作线程独立处理
- GroupByWrapper类中保存了匹配的聚合列的信息,这些信息在每个工作线程中是相同的,是否要将聚合列的信息拆解到一个独立的数据结构里, 各个工作线程中只读
- 是否还要使用当前的GroupByWrapper类与GroupTable类, GroupDistinctTable类与GroupDistinctCache这样的封装层级, 这样的封装对功能是否真的起到了正确的切割作用? 维护成本如何? 是否已经是最优化的类组织结构?
- ValueMatchingTable类此前是存储聚合的数据, 现在要用parallel hash map取代, 否则就需要在每个工作线程中存储数据,最后再将各个工作线程中的数据拷贝到一起做一次全局的聚合处理运算, 内存拷贝的性能开销是巨大的, 不可接受。替换局部hash时, parallel hash map类的接口如何与上层遍历聚合的逻辑结合?
- parallel hash map在写入聚合数据时, 如何同时与已经存在的数据也进行聚合运算汇总成统一的结果?如何保证聚合汇总结果的正确性?
- parallel hash map涉及到多线程竞争写同一个聚合条件的值时, 锁的使用规则是什么? 如何避免不同工作线程的结果的覆盖?
剥离处理聚合的列属性:
- 处理聚合的列,其元属性独立于特定元组, 而且是不变的,可进行剥离
- GroupByWrapper类中保留在遍历元组过程中与元组相关的数据,例如已处理的行, 已被聚合处理过的数据等