Skip to content

Commit bd701d8

Browse files
committed
refine storage-format and add bench test
1 parent 2033d9d commit bd701d8

6 files changed

Lines changed: 144 additions & 86 deletions

File tree

docs/table-design/storage-format.md

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,38 +24,52 @@ specific language governing permissions and limitations
2424
under the License.
2525
-->
2626

27-
Doris Storage Format V3 is a major evolution from the Segment V2 format. Through metadata decoupling and encoding strategy optimization, it specifically improves performance for wide tables, complex data types (such as Variant), and cloud-native storage-compute separation scenarios.
27+
Storage Format V3 is the successor to Segment V2. The main change: column metadata is no longer packed inside the Segment Footer, but stored in a separate area of the file. This removes the metadata bottleneck that V2 hits when tables grow to thousands of columns — a common situation with `VARIANT` subcolumns.
2828

29-
## Key Optimizations
29+
## What Changed
3030

3131
### External Column Meta
32-
* **Background**: In Segment V2, metadata for all columns (`ColumnMetaPB`) is stored in the Footer of the Segment file. For wide tables with thousands of columns or auto-scaling Variant scenarios, the Footer can grow to several megabytes.
33-
* **Optimization**: V3 decouples `ColumnMetaPB` from the Footer and stores it in a separate area within the file (External Column Meta Area).
34-
* **Benefits**:
35-
* **Ultra-fast Metadata Loading**: Significantly reduces Segment Footer size, speeding up initial file opening.
36-
* **On-demand Loading**: Metadata can be loaded on demand from the independent area, reducing memory usage and improving cold start query performance on object storage (like S3/OSS).
32+
33+
In V2, every column's `ColumnMetaPB` sits in the Segment Footer. When a table has thousands of columns (or a `VARIANT` column expands into thousands of subcolumns), the Footer alone can reach several MB. Opening a Segment means loading and deserializing all of that, even if the query only touches two columns.
34+
35+
V3 moves `ColumnMetaPB` out of the Footer into a dedicated area in the file. The Footer keeps only lightweight pointers.
36+
37+
![Storage Format V2 vs V3 — Segment File Layout](/images/variant/storage-format-v3-layout.png)
38+
39+
Result: the system loads a small Footer first, then fetches metadata only for the columns the query needs. On object storage (S3, OSS), this cuts cold-start latency considerably.
3740

3841
### Integer Type Plain Encoding
39-
* **Optimization**: V3 defaults to `PLAIN_ENCODING` (raw binary storage) for numerical types (such as `INT`, `BIGINT`), instead of the traditional BitShuffle.
40-
* **Benefits**: Combined with LZ4/ZSTD compression, `PLAIN_ENCODING` provides higher read throughput and lower CPU overhead. In modern high-speed IO environments, this "trading decompression for performance" strategy offers a clear advantage when scanning large volumes of data.
42+
43+
V3 switches the default encoding for numeric types (`INT`, `BIGINT`, etc.) from BitShuffle to `PLAIN_ENCODING` (raw binary). With LZ4 or ZSTD compression on top, this combination reads faster and uses less CPU than BitShuffle during large scans.
4144

4245
### Binary Plain Encoding V2
43-
* **Optimization**: Introduces `BINARY_PLAIN_ENCODING_V2`, using a `[length(varuint)][raw_data]` streaming layout, replacing the old format that relied on trailing offset tables.
44-
* **Benefits**: Eliminates large trailing offset tables, making data storage more compact and significantly reducing storage consumption for string and JSONB types.
4546

46-
## Design Philosophy
47-
The design philosophy of V3 can be summarized as: **"Metadata Decoupling, Encoding Simplification, and Streaming Layout"**. By reducing metadata processing bottlenecks and leveraging the high efficiency of modern CPUs in processing simple encodings, it achieves high-performance analysis under complex schemas.
47+
V3 introduces `BINARY_PLAIN_ENCODING_V2` for strings and JSONB. The new layout uses `[length(varuint)][raw_data]` in a streaming fashion, eliminating the trailing offset table that V2 required. This makes string storage more compact.
48+
49+
## Performance
50+
51+
The following test was run on a VARIANT table with 10,000 Segments, each containing 7,000 JSON paths — all materialized as subcolumns.
52+
53+
![Storage Format V3 — Metadata Open Efficiency](/images/variant/storage-format-v3-benchmark.png)
54+
55+
| Metric | V2 | V3 | Improvement |
56+
|---|---:|---:|---|
57+
| Segment open time | 65 s | 4 s | 16× faster |
58+
| Memory during open | 60 GB | < 1 GB | 60× less |
59+
60+
With V2, the system must deserialize the entire Footer (containing all column metadata) even when the query reads only a few columns. That causes massive I/O and memory waste. V3 reads a slim Footer, then loads column metadata on demand.
61+
62+
## When to Use V3
63+
64+
- Tables with 2,000+ columns or VARIANT columns expanding into many subcolumns.
65+
- Object storage or tiered storage where metadata loading latency matters.
66+
- Any new `VARIANT` table — V3 is always recommended.
4867

49-
## Use Cases
50-
- **Wide Tables**: Tables with more than 2000 columns or long column names.
51-
- **Semi-structured Data**: Heavy use of `VARIANT` or `JSON` types.
52-
- **Tiered Storage/Cloud Native**: Scenarios sensitive to object storage loading latency.
53-
- **High-performance Scanning**: Analytical tasks with extreme requirements for scan throughput.
68+
For tables with a moderate number of columns and no VARIANT, V2 works fine. V3 helps most when the column count is large.
5469

5570
## Usage
5671

57-
### Enable When Creating a New Table
58-
Specify `storage_format` as `V3` in the `PROPERTIES` of the `CREATE TABLE` statement:
72+
Specify `storage_format` as `V3` in `PROPERTIES` when creating a table:
5973

6074
```sql
6175
CREATE TABLE table_v3 (

i18n/zh-CN/docusaurus-plugin-content-docs/current/table-design/storage-format.md

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,38 +24,53 @@ specific language governing permissions and limitations
2424
under the License.
2525
-->
2626

27-
Apache Doris 存储格式 V3 是在 Segment V2 格式基础上进行的重大演进。它通过元数据解耦与编码策略优化,专门针对大宽表、复杂数据类型(如 Variant)以及云原生存算分离场景提升性能
27+
存储格式 V3 Segment V2 的继任者。核心变化:列元数据不再打包在 Segment Footer 中,而是存储到文件内的独立区域。这去掉了 V2 在列数达到几千时遇到的元数据瓶颈——在 `VARIANT` 子列自动扩展后,这是常见场景
2828

29-
## 核心优化点
29+
## 改了什么
3030

31-
### 外部列元数据 (External Column Meta)
32-
* **优化背景**:在 Segment V2 中,所有列的元数据(`ColumnMetaPB`)都存储在 Segment 文件的 Footer 中。对于拥有数千列的大宽表或自动扩容的 Variant 场景,Footer 可能会膨胀到几 MB。
33-
* **优化思路**:V3 将 `ColumnMetaPB` 从 Footer 中剥离,转而存储在文件内的独立区域(External Column Meta Area)。
34-
* **收益**
35-
* **极速元数据加载**:显著减小 Segment Footer 体积,加快文件初次打开速度。
36-
* **按需加载**:元数据可以按需从独立区域加载,降低内存占用,提升对象存储(如 S3/OSS)上的冷启动查询性能。
31+
### 外部列元数据(External Column Meta)
3732

38-
### 数值类型 Plain 编码模式 (Integer Type Plain Encoding)
39-
* **优化思路**:V3 默认将数值类型(如 `INT`, `BIGINT`)切换为 `PLAIN_ENCODING`(原始二进制存储),而非传统的 BitShuffle。
40-
* **收益**:配合 LZ4/ZSTD 压缩时,`PLAIN_ENCODING` 提供了更高的读取吞吐量和更低的 CPU 开销。在现代高速 IO 环境下,这种“解压换性能”的策略在扫描大体量数据时优势明显。
33+
V2 中,所有列的 `ColumnMetaPB` 都放在 Segment Footer 里。当表有几千列(或一个 `VARIANT` 列展开为几千个子列)时,Footer 可以膨胀到几 MB。打开一个 Segment 就要加载和反序列化全部元数据,即使查询只需读两个列。
4134

42-
### 二进制 Plain 编码 V2 (Binary Plain Encoding V2)
43-
* **优化思路**:引入 `BINARY_PLAIN_ENCODING_V2`,采用 `[长度(varuint)][原始数据]` 的流式布局,取代了依赖末尾偏移表(Offsets)的旧格式。
44-
* **收益**:消除了末尾庞大的偏移表,数据存储更加紧凑,有效降低了字符串和 JSONB 类型的存储空间占用。
35+
V3 将 `ColumnMetaPB` 从 Footer 移到文件内的独立区域,Footer 只保留轻量指针。
4536

46-
## 设计哲学
47-
V3 的设计哲学可以总结为:**“元数据解耦、编码简化、流式布局”**。通过减少元数据处理瓶颈和利用现代 CPU 对简单编码的高处理效率,实现在复杂模式下的高性能分析。
37+
![存储格式 V2 vs V3 — Segment 文件布局](/images/variant/storage-format-v3-layout.png)
4838

49-
## 使用场景
50-
- **大宽表**:字段数量超过 2000 个以上,或字段名冗长。
51-
- **半结构化数据**:大量使用 `VARIANT`, 且物化列数超过2000列。
52-
- **冷热分离/云原生**:对对象存储加载延迟敏感的场景。
53-
- **高性能扫描**:对 Scan 吞吐量有极致要求的分析任务。
39+
结果:系统先加载一个很小的 Footer,再按需拉取查询所需列的元数据。在对象存储(S3、OSS)上,冷启动延迟大幅降低。
40+
41+
### 数值类型 Plain 编码
42+
43+
V3 将数值类型(`INT``BIGINT` 等)的默认编码从 BitShuffle 换成 `PLAIN_ENCODING`(原始二进制存储)。配合 LZ4 或 ZSTD 压缩,读取速度更快、CPU 开销更低,在大批量扫描时优势明显。
44+
45+
### 二进制 Plain 编码 V2
46+
47+
V3 为字符串和 JSONB 引入 `BINARY_PLAIN_ENCODING_V2`。新布局采用 `[长度(varuint)][原始数据]` 流式结构,去掉了 V2 需要的末尾偏移表,存储更紧凑。
48+
49+
## 性能数据
50+
51+
以下测试在一张 VARIANT 表上进行,共 10,000 个 Segment,每个 Segment 包含 7,000 个 JSON Path,全部物化为子列。
52+
53+
![存储格式 V3 — 元数据打开效率](/images/variant/storage-format-v3-benchmark.png)
54+
55+
| 指标 | V2 | V3 | 提升 |
56+
|---|---:|---:|---|
57+
| Segment 打开时间 | 65 s | 4 s | 快 16 倍 |
58+
| 打开时内存占用 | 60 GB | < 1 GB | 降低 60 倍 |
59+
60+
V2 必须反序列化整个 Footer(包含全部列元数据),即使查询只读几列,也会产生大量无效 I/O 和内存浪费。V3 只读一个精简 Footer,再按需加载列元数据。
61+
62+
## 什么时候用 V3
63+
64+
- 表有 2,000 列以上,或 VARIANT 列展开了大量子列。
65+
- 使用对象存储或分层存储,元数据加载延迟敏感。
66+
- 新建的 `VARIANT` 表——始终建议开启 V3。
67+
68+
列数不多、不使用 VARIANT 的普通表,V2 也够用。V3 在列数量大的场景收益最明显。
5469

5570
## 使用方式
5671

57-
### 创建新表时启用
58-
在建表语句的 `PROPERTIES` 中指定 `storage_format``V3`
72+
建表时在 `PROPERTIES` 中指定 `storage_format``V3`
73+
5974
```sql
6075
CREATE TABLE table_v3 (
6176
id BIGINT,

i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/table-design/storage-format.md

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,38 +24,53 @@ specific language governing permissions and limitations
2424
under the License.
2525
-->
2626

27-
Apache Doris 存储格式 V3 是在 Segment V2 格式基础上进行的重大演进。它通过元数据解耦与编码策略优化,专门针对大宽表、复杂数据类型(如 Variant)以及云原生存算分离场景提升性能
27+
存储格式 V3 Segment V2 的继任者。核心变化:列元数据不再打包在 Segment Footer 中,而是存储到文件内的独立区域。这去掉了 V2 在列数达到几千时遇到的元数据瓶颈——在 `VARIANT` 子列自动扩展后,这是常见场景
2828

29-
## 核心优化点
29+
## 改了什么
3030

31-
### 外部列元数据 (External Column Meta)
32-
* **优化背景**:在 Segment V2 中,所有列的元数据(`ColumnMetaPB`)都存储在 Segment 文件的 Footer 中。对于拥有数千列的大宽表或自动扩容的 Variant 场景,Footer 可能会膨胀到几 MB。
33-
* **优化思路**:V3 将 `ColumnMetaPB` 从 Footer 中剥离,转而存储在文件内的独立区域(External Column Meta Area)。
34-
* **收益**
35-
* **极速元数据加载**:显著减小 Segment Footer 体积,加快文件初次打开速度。
36-
* **按需加载**:元数据可以按需从独立区域加载,降低内存占用,提升对象存储(如 S3/OSS)上的冷启动查询性能。
31+
### 外部列元数据(External Column Meta)
3732

38-
### 数值类型 Plain 编码模式 (Integer Type Plain Encoding)
39-
* **优化思路**:V3 默认将数值类型(如 `INT`, `BIGINT`)切换为 `PLAIN_ENCODING`(原始二进制存储),而非传统的 BitShuffle。
40-
* **收益**:配合 LZ4/ZSTD 压缩时,`PLAIN_ENCODING` 提供了更高的读取吞吐量和更低的 CPU 开销。在现代高速 IO 环境下,这种“解压换性能”的策略在扫描大体量数据时优势明显。
33+
V2 中,所有列的 `ColumnMetaPB` 都放在 Segment Footer 里。当表有几千列(或一个 `VARIANT` 列展开为几千个子列)时,Footer 可以膨胀到几 MB。打开一个 Segment 就要加载和反序列化全部元数据,即使查询只需读两个列。
4134

42-
### 二进制 Plain 编码 V2 (Binary Plain Encoding V2)
43-
* **优化思路**:引入 `BINARY_PLAIN_ENCODING_V2`,采用 `[长度(varuint)][原始数据]` 的流式布局,取代了依赖末尾偏移表(Offsets)的旧格式。
44-
* **收益**:消除了末尾庞大的偏移表,数据存储更加紧凑,有效降低了字符串和 JSONB 类型的存储空间占用。
35+
V3 将 `ColumnMetaPB` 从 Footer 移到文件内的独立区域,Footer 只保留轻量指针。
4536

46-
## 设计哲学
47-
V3 的设计哲学可以总结为:**“元数据解耦、编码简化、流式布局”**。通过减少元数据处理瓶颈和利用现代 CPU 对简单编码的高处理效率,实现在复杂模式下的高性能分析。
37+
![存储格式 V2 vs V3 — Segment 文件布局](/images/variant/storage-format-v3-layout.png)
4838

49-
## 使用场景
50-
- **大宽表**:字段数量超过 2000 个以上,或字段名冗长。
51-
- **半结构化数据**:大量使用 `VARIANT`, 且物化列数超过2000列。
52-
- **冷热分离/云原生**:对对象存储加载延迟敏感的场景。
53-
- **高性能扫描**:对 Scan 吞吐量有极致要求的分析任务。
39+
结果:系统先加载一个很小的 Footer,再按需拉取查询所需列的元数据。在对象存储(S3、OSS)上,冷启动延迟大幅降低。
40+
41+
### 数值类型 Plain 编码
42+
43+
V3 将数值类型(`INT``BIGINT` 等)的默认编码从 BitShuffle 换成 `PLAIN_ENCODING`(原始二进制存储)。配合 LZ4 或 ZSTD 压缩,读取速度更快、CPU 开销更低,在大批量扫描时优势明显。
44+
45+
### 二进制 Plain 编码 V2
46+
47+
V3 为字符串和 JSONB 引入 `BINARY_PLAIN_ENCODING_V2`。新布局采用 `[长度(varuint)][原始数据]` 流式结构,去掉了 V2 需要的末尾偏移表,存储更紧凑。
48+
49+
## 性能数据
50+
51+
以下测试在一张 VARIANT 表上进行,共 10,000 个 Segment,每个 Segment 包含 7,000 个 JSON Path,全部物化为子列。
52+
53+
![存储格式 V3 — 元数据打开效率](/images/variant/storage-format-v3-benchmark.png)
54+
55+
| 指标 | V2 | V3 | 提升 |
56+
|---|---:|---:|---|
57+
| Segment 打开时间 | 65 s | 4 s | 快 16 倍 |
58+
| 打开时内存占用 | 60 GB | < 1 GB | 降低 60 倍 |
59+
60+
V2 必须反序列化整个 Footer(包含全部列元数据),即使查询只读几列,也会产生大量无效 I/O 和内存浪费。V3 只读一个精简 Footer,再按需加载列元数据。
61+
62+
## 什么时候用 V3
63+
64+
- 表有 2,000 列以上,或 VARIANT 列展开了大量子列。
65+
- 使用对象存储或分层存储,元数据加载延迟敏感。
66+
- 新建的 `VARIANT` 表——始终建议开启 V3。
67+
68+
列数不多、不使用 VARIANT 的普通表,V2 也够用。V3 在列数量大的场景收益最明显。
5469

5570
## 使用方式
5671

57-
### 创建新表时启用
58-
在建表语句的 `PROPERTIES` 中指定 `storage_format``V3`
72+
建表时在 `PROPERTIES` 中指定 `storage_format``V3`
73+
5974
```sql
6075
CREATE TABLE table_v3 (
6176
id BIGINT,
335 KB
Loading
371 KB
Loading

0 commit comments

Comments
 (0)