java类的存储结构设计_Doris存储层设计介绍1——存储结构
设计解析
1 整体介绍
Doris是基于MPP架构的交互式SQL数据仓库,主要⽤于解决了近实时的报表和多维分析。Doris⾼效的导⼊、查询离不开其存储结构精巧的设计。本⽂主要通过阅读Doris BE模块代码,详细分析了Doris BE模块存储层的实现原理,阐述和解密Doris⾼效的写⼊、查询能⼒背后的核⼼技术。其中包括Doris列存的设计、索引设计、数据读写流程、Compaction流程、Tablet和Rowset的版本管理、数据备份等功能。这⾥会通过三篇⽂章来逐步进⾏介绍,分别为《Doris存储层设计介绍1——存储结构设计解析》、《Doris存储层设计介绍2——读写、compaction流程分析》、《Doris存储层设计介绍3——Tablet管理、数据备份》。
Doris :
本⽂为第⼀篇《Doris存储层设计介绍1——存储结构设计解析》,⽂章介绍了Segment V2版本的存储层结构,包括了有序存储、稀疏索引、前缀索引、位图索引、BloomFilter等丰富功能,可以应对各种复杂的场景提供极速的查询能⼒。
2 设计⽬标
批量导⼊,少量更新
绝⼤多数的读请求
宽表场景,读取⼤量⾏,少量列
⾮事务场景
良好的扩展性
3 存储⽂件格式
3.1 存储⽬录结构
存储层对存储数据的管理通过storage_root_path路径进⾏配置,路径可以是多个。存储⽬录下⼀层按照分桶进⾏组织,分桶⽬录下存放具体的tablet,按照tablet_id命名⼦⽬录。
Segment⽂件存放在tablet_id⽬录下按SchemaHash管理。Segment⽂件可以有多个,⼀般按照⼤⼩进⾏分割,默认为256MB。其
中,Segment v2⽂件命名规则为:${rowset_id}_${segment_id}.dat。具体存储⽬录存放格式如下图所⽰:
3.2 Segment v2⽂件结构
Segment整体的⽂件格式分为数据区域,索引区域和footer三个部分,如下图所⽰:
Data Region:⽤于存储各个列的数据信息,这⾥的数据是按需分page加载的
Index Region: Doris中将各个列的index数据统⼀存储在Index Region,这⾥的数据会按照列粒度进⾏加载,所以跟列的数据信息分开存储
Footer信息
SegmentFooterPB:定义⽂件的元数据信息
4个字节的FooterPB内容的checksum
4个字节的FileFooterPB消息长度,⽤于读取FileFooterPB
8个字节的MAGIC CODE,之所以在末位存储,是⽅便不同的场景进⾏⽂件类型的识别
下⾯分布介绍各个部分的存储格式的设计。
4 Footer信息
Footer信息段在⽂件的尾部,存储了⽂件的整体结构,包括数据域的位置,索引域的位置等信息,其中有
SegmentFooterPB,CheckSum,Length,MAGIC CODE 4个部分。
SegmentFooterPB数据结构如下:
SegmentFooterPB采⽤了PB格式进⾏存储,主要包含了列的meta信息、索引的meta信息,Segment的short key索引信息、总⾏数。
4.1 列的meta信息
ColumnId:当前列在schema中的序号
UniqueId:全局唯⼀的id
Type:列的类型信息
Length:列的长度信息
Encoding:编码格式
Compression:压缩格式
Dict PagePointer:字典信息
4.2 列索引的meta信息
OrdinalIndex:存放列的稀疏索引meta信息。
ZoneMapIndex:存放ZoneMap索引的meta信息,内容包括了最⼤值、最⼩值、是否有空值、是否没有⾮空值。SegmentZoneMap存放了全局的ZoneMap信息,PageZoneMaps则存放了每个页⾯的统计信息。
BitMapIndex:存放BitMap索引的meta信息,内容包括了BitMap类型,字典数据BitMap数据。
BloomFilterIndex:存放了BloomFilter索引信息。
为了防⽌索引本⾝数据量过⼤,ZoneMapIndex、BitMapIndex、BloomFilterIndex采⽤了两级的Page管理。对应了IndexColumnMeta 的结构,当⼀个Page能够放下时,当前Page直接存放索引数据,即采⽤1级结构;当⼀个Page⽆法放下时,索引数据写⼊新的Page
中,Root Page存储数据Page的地址信息。
5 Ordinal Index(⼀级索引)
Ordinal Index索引提供了通过⾏号来查Column Data Page数据页的物理地址。Ordinal Index能够将按列存储数据按⾏对齐,可以理解为⼀级索引。其他索引查数据时,都要通过Ordinal Index查数据Page的位置。因此,这⾥先介绍Ordinal Index索引。
在⼀个segment中,数据始终按照key(AGGREGATE KEY、UNIQ KEY 和 DUPLICATE KEY)排序顺序进⾏存储,即key的排序决定了数据存储的物理结构。确定了列数据的物理结构顺序,在写⼊数据时,Column Data Page是由Ordinal index进⾏管理,Ordinal index记录了每个Column Data Page的位置offset、⼤⼩size和第⼀个数据项⾏号信息,即Ordinal。这样每个列具有按⾏信息进⾏快速扫描的能⼒。Ordinal index采⽤的稀疏索引结构,就像是⼀本书⽬录,记录了每个章节对应的页码。
5.1 存储结构
Ordinal index元信息存储在SegmentFooterPB中的每个列的OrdinalIndexMeta中。具体结构如下图所⽰:
在OrdinalIndexMeta中存放了索引数据对应的root page地址,这⾥做了⼀些优化,当数据仅有⼀个page时,这⾥的地址可以直接指向唯⼀的数据page;当⼀个page放不下时,指向OrdinalIndex类型的⼆级结构索引page,索引数据中每个数据项对应了Column Data Page offset位置、size⼤⼩和ordinal⾏号信息。其中Ordinal index索引粒度与page粒度⼀致,默认64*1024字节。
6、列数据存储
Column的data数据按照Page为单位分块存储,每个Page⼤⼩⼀般为64*1024个字节。Page在存储的位置和⼤⼩由ordinal index管理。
6.1 data page存储结构
DataPage主要为Data部分、Page Footer两个部分。
Data部分存放了当前Page的列的数据。当允许存在Null值时,对空值单独存放了Null值的Bitmap,由RLE格式编码通过bool类型记录Null 值的⾏号。
Page Footer包含了Page类型Type、UncompressedSize未压缩时的数据⼤⼩、FirstOrdinal当前Page第⼀⾏的RowId、NumValues为当前Page的⾏数、NullMapSize对应了NullBitmap的⼤⼩。
6.2 数据压缩
针对不同的字段类型采⽤了不同的编码。默认情况下,针对不同类型采⽤的对应关系如下:
TINYINT/SMALLINT/INT/BIGINT/LARGEINT
BIT_SHUFFLE
FLOAT/DOUBLE/DECIMAL
BIT_SHUFFLE
CHAR/VARCHAR
DICT
BOOL
RLE
DATE/DATETIME
BIT_SHUFFLE
java中index是什么意思HLL/OBJECT
PLAIN
默认采⽤LZ4F格式对数据进⾏压缩。
7、Short Key Index索引
7.1 存储结构
Short Key Index前缀索引,是在key(AGGREGATE KEY、UNIQ KEY 和 DUPLICATE KEY)排序的基础上,实现的⼀种根据给定前缀列,快速查询数据的索引⽅式。这⾥Short Key Index索引也采⽤了稀疏索引结构,在数据写⼊过程中,每隔⼀定⾏数,会⽣成⼀个索引项。这个⾏数为索引粒度默认为1024⾏,可配置。该过程如下图所⽰:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论