OceanBase行存版本中行列混存编码实现

【 使用环境 】生产环境 or 测试环境
【 OB or 其他组件 】OB
【 使用版本 】4.2
【问题描述】OceanBase是使用行列混存编码实现的,在微块中存储方式是行存还是列存呢?
根据https://open.oceanbase.com/blog/8000132的说法,数据在微块中是行存的,但是encoding按列编码之后可能行的数量都会改变,比如RLE编码,OceanBase 社区
【复现路径】问题出现前后相关操作
【附件及日志】推荐使用OceanBase敏捷诊断工具obdiag收集诊断信息,详情参见链接(右键跳转查看):

【SOP系列 22 】——故障诊断第一步(自助诊断和诊断信息收集)

【备注】基于 LLM 和开源文档 RAG 的论坛小助手已开放测试,在发帖时输入 [@论坛小助手] 即可召唤小助手,欢迎试用!

根据文档库中的信息,OceanBase 数据库的微块中数据的存储方式是行列混存的。具体来说:

  • 在 OceanBase 数据库中,微块有两种存储格式:flat 微块(未编码)和 encoding 微块(编码)。对于 encoding 格式的微块,它并不是简单的行存或列存,而是采用了行列混存的方式。
  • 在 Encoding 微块中,逻辑上仍然是一组行的数据存在微块里,但微块会按列对数据进行编码。编码后的定长数据存储在微块内部的列存区,部分变长数据还是按行存储在变长区。这意味着虽然数据是以行为单位组织的,但在实际存储时,同一列的数据会被集中在一起进行编码和压缩。
  • 这种设计使得即使经过如 RLE(Run-Length Encoding)等编码后行的数量发生变化,微块依然能够保持按行存储的特性。当需要读取微块中的一行数据时,可以只对该行数据进行解码,避免了解压整个数据块的问题;同时,在向量化执行过程中也可以对指定的列进行解码,降低了投影操作的开销。

因此,尽管 Encoding 可能改变行的数量,但通过将相同列的数据集中编码并存储,OceanBase 能够确保微块内的数据既具有按列编码的优势,又能在物理结构上维持按行存储的形式。这保证了数据读取时的高效性和灵活性。

以上信息来源于《OceanBase 数据库自研了一套对数据库进行行列混存编码的压缩方法》章节内容。

更多信息请查看:

  1. OceanBase AP 核心特性
  2. 列存 FAQ
  3. 表存储
  4. 压缩与编码
  5. 集群管理 FAQ
  6. OceanBase 术语
  7. MemTable

@论坛小助手 编码后的定长数据存储在微块内部的列存区,部分变长数据还是按行存储在变长区,这句话怎么理解,定长数据喝变长数据有例子吗

根据文档库中的信息,OceanBase 数据库在微块中采用了行列混存的编码方式。为了更好地理解“编码后的定长数据存储在微块内部的列存区,部分变长数据还是按行存储在变长区”,我们可以分点详细解释,并给出具体的例子。

1. 定长数据与变长数据的区别

  • 定长数据:指每个字段占用的字节数是固定的。例如:

    • 整数类型(如 INTBIGINT
    • 固定长度字符串(如 CHAR(10)
  • 变长数据:指每个字段占用的字节数是可变的。例如:

    • 可变长度字符串(如 VARCHAR(255)
    • 大文本字段(如 TEXT
    • 二进制大对象(如 BLOB

2. 行列混存编码的具体实现

编码后的定长数据存储在列存区

  • 列存区:在同一列内的所有数据会被集中在一起进行编码和压缩。由于这些数据具有相同的类型和长度,因此可以更高效地进行压缩。
  • 例子:假设有一列 age INT,该列的所有数据都是整数类型,每条记录占用4个字节。经过编码后,这些整数会集中存储在列存区内,形成一个连续的内存区域。

部分变长数据按行存储在变长区

  • 变长区:对于变长数据,它们仍然按照原始的行结构进行存储,但只存储那些无法有效压缩或不适合按列存储的数据。
  • 例子:假设有一列 name VARCHAR(255),该列的数据长度不固定。经过编码后,这些变长字符串会按行存储在变长区内,每行数据的长度可能不同。

3. 具体例子说明

假设我们有一个表 employees,包含以下列:

id (INT) name (VARCHAR(255)) age (INT) address (TEXT)
1 Alice 30 Address 1
2 Bob 25 Address 2
3 Charlie 35 Address 3

在这个表中:

  • idage 是定长数据,会存储在列存区。
  • nameaddress 是变长数据,会存储在变长区。

具体存储方式如下:

  • 列存区

    • id 列:[1, 2, 3]
    • age 列:[30, 25, 35]
  • 变长区

    • 第一行:name = "Alice", address = "Address 1"
    • 第二行:name = "Bob", address = "Address 2"
    • 第三行:name = "Charlie", address = "Address 3"

4. 优势

这种行列混存的方式结合了行存和列存的优点:

  • 列存区:便于对同一列数据进行高效的压缩和编码,减少了存储空间。
  • 变长区:保持了行存的灵活性,使得读取特定行的数据时不需要解压整个数据块,提高了查询性能。

以上信息来源于《OceanBase 数据库自研了一套对数据库进行行列混存编码的压缩方法》章节内容。希望这个解释能帮助您更好地理解 OceanBase 的编码和存储机制。如果有更多问题,欢迎继续提问!

具体信息可参考以下文档:

  1. OceanBase 术语
  2. 表存储
  3. 压缩与编码
  4. 列存 FAQ
  5. 集群管理 FAQ
  6. 数据库对象存储
  7. 发现磁盘的静默错误
  8. 配置磁盘数据文件的动态扩容

变长的varchar不能encoding编码压缩吗?只有定长的字段才可以?

根据文档库中的信息,变长的 VARCHAR 字段是可以进行编码和压缩的。OceanBase 数据库在处理变长数据时采用了灵活的编码策略,以确保既能高效压缩又能保持查询性能。以下是详细的解释:

1. 变长字段的编码与压缩

  • 变长字段(如 VARCHAR)可以使用多种编码方式,包括但不限于:
    • Run-Length Encoding (RLE):对于重复值较多的数据非常有效。
    • Dictionary Encoding:将常见的字符串映射到较小的整数,减少存储空间。
    • Prefix Compression:对前缀相同的字符串进行压缩。
    • LZ4、ZLIB 等通用压缩算法。

这些编码方式不仅适用于定长字段,也适用于变长字段。实际上,变长字段由于其长度不固定,往往更能从编码和压缩中受益,因为它们通常包含更多的冗余信息。

2. 编码后的存储方式

  • 列存区:即使对于变长字段,经过编码后,如果编码结果是定长或近似定长的(例如通过字典编码),这些编码后的数据仍然可以存储在列存区内。
  • 变长区:对于那些无法有效编码为定长格式的变长数据,仍然会按行存储在变长区内,但已经过压缩,减少了存储空间。

3. 具体例子

假设我们有一个表 employees,其中包含一个 VARCHAR(255) 类型的 name 列:

id (INT) name (VARCHAR(255))
1 Alice
2 Bob
3 Charlie

编码前

  • name 列的数据长度不固定,每条记录占用的空间不同。

编码后

  • 使用 字典编码,假设 Alice 映射为 1Bob 映射为 2Charlie 映射为 3
  • 编码后的 name 列变为 [1, 2, 3],每个值占用固定的1个字节。
  • 这些编码后的定长数据可以存储在列存区内,而原始的变长字符串则存储在一个单独的字典表中。

4. 编码与压缩的优势

  • 高效压缩:变长字段通常包含大量重复或相似的数据,编码和压缩可以显著减少存储空间。
  • 快速查询:编码后的定长数据便于索引和快速检索,提升了查询性能。
  • 灵活性:即使是变长字段,也可以根据具体数据特征选择最合适的编码方式,确保最佳的压缩效果和查询性能。

5. 实际应用

在实际应用中,OceanBase 数据库会自动选择最适合的编码方式,用户无需手动指定。数据库会根据数据分布和查询模式动态调整编码策略,以达到最佳的存储和查询性能。

因此,变长的 VARCHAR 字段不仅可以进行编码和压缩,而且在很多情况下能够从中获得显著的性能提升和存储节省。

以上信息来源于《OceanBase 数据库自研了一套对数据库进行行列混存编码的压缩方法》章节内容。希望这个解释能帮助您更好地理解 OceanBase 的编码和压缩机制。如果有更多问题,欢迎继续提问!

具体信息可参考以下文档:

  1. OceanBase 术语
  2. 表存储
  3. 压缩与编码
  4. 列存 FAQ
  5. 集群管理 FAQ

详情请参考:

  1. 客户端编程语言
  2. CHAR 和 VARCHAR
  3. 字符类型
  4. 列类型变更规则
  5. oceanbase.DBA_OB_BACKUP_PARAMETER
  6. V$OB_COMPATIBILITY_CONTROL

(小助手的答复已结束,如未能解决您的问题,请继续提问并等待其他同学的回复,谢谢!)

之前的描述有点不正确。定长和变长不是指原始数据是定长还是变长,而是编码以后得数据是定长和变长。所有的列都会编码,比如varchar如果是字典编码那么编码以后就是定长的,那么这个也是按照列存储的,因为按照特定偏移定位比较简单。如果编码以后的数据是变长的,那么就按照行存储了,可能需要一些辅助结构来帮忙定位。

好的,所以还是看具体的数据分布对吗,比如如果varchar字段长度不一并且NDV很大,这时候不适合用字典编码,可能用其它编码方式编码以后数据还是变长的,可能就需要行存了?

是的。这是ob行存表的实现。ob列存表,所有的列都是列存的。