Doris的数据模型-聚合模型
概述:
数据进入doris时会根据key进行聚合操作,落盘的实际数据是聚合后的结果,节省了大量的IO消耗。导入数据之前可能有1亿条,进入doris后可能就只有1千万条了,查询自然也快了很多。聚合模型非常适合做报表统计分析、多维分析的业务。
应用场景:
适合做报表统计分析、多维分析业务。
实现思想:
将导入数据分为三个级别,base(最早导入的数据)+delta(增量部分的数据)=newBase(生成新的base)。
详细合并过程:
每一次导入都会生成一个delta版本文件,比如一天导入了10次数据,那么就会有10个delta版本在doris中,当delta版本数量为10时进行一次compaction,合并成一个大的delta。大的delta会和Base进行一次合并形成新的Base版本文件。分级合并文件的目的其实就是想尽量把小文件合并成一个中等规模的文件,然后再把中等规模的文件合并成一个大文件,这样会减少一个大文件直接跟一个小文件合并的读写放大量。因为大文件大量的读取其实是划不来的,所以Doris采用一个分级的策略去做整个的合并。同时这样做还有一个好处就是新来的导入,不会影响正在进行的查询。因为我现在的导入只有在整个批次完成的时候(也就是我们前面所讲的FE的元数据)才能感知到,这样它可以做到一个比较好的读写分离,用户在查询历史数据不会受到新来导入的影响。
数据聚发生的时机:
- 每一批次数据导入的 ETL 阶段。该阶段会在每一批次导入的数据内部进行聚合。
- 底层 BE 进行数据 Compaction 的阶段。该阶段,BE 会对已导入的不同批次的数据进行进一步的聚合。
- 数据查询阶段。在数据查询时,对于查询涉及到的数据,会进行对应的聚合。
聚合模型的小坑:
- 用户查询底层未聚合:在查询引擎中加入了聚合算子(聚合算子必与建表语句中的聚合类型一致),来保证数据对外的一致性。(如果你查询语句中不用聚合算子的话,数据在底层很可能还没有发生聚合,查出来的数据可能有问题,需要我们强制性聚合,就是加入聚合算子)
- 计数可能会有问题:select count(*)在doris中非常耗时,我们可以直接某一个key列进行计数 。但是在聚合模型查出的结果不一定正确,因为此时可能并未聚合。此时要想获取正确的结果应该加上所有的key列和建表时指定的聚合函数。如果有频繁的count()操作时,我们应该这样设计,增加一列恒为1的值,聚合类型为sum的列来模拟count(),但是这也只能表述原始导入的行数而不是聚合后的结果。所以,需要一种万全的方案,将count列的聚合类型改为Replace,且依然值恒为1.这种方式没有导入重复行的限制,是表中数据的最终行数。