[Feature] Support shared-shredding storage layout for MAP columns
@lszskye 已经在做这个了。
开始于 2026年9月21日。
评估
调研方向
从 PIP-43 开始,跟踪现有的 FormatWriter、FileBatchReader、AppendOnlyWriter、LeafPredicate 和 PredicateConverter 接口。在实现 schema 转换、metadata、分配、predicate 翻译和重构部分之前,先梳理写入和读取路径。完成的标准是,使用 shared-shredding 的 MAP 列能够在写入、读取、过滤、overflow 以及文件之间 K 值不同时正常工作。
由索引模型根据 Issue 内容生成。
描述
Search before asking
- I searched in the issues and found nothing similar.
Motivation
In time-series / IoT / observability workloads, a common pattern is storing free-schema fields in a MAP<STRING, T> column (e.g. metrics MAP<STRING, DOUBLE>). The default MAP storage (two KV arrays) provides:
- No per-key columnar access
- No per-key statistics
- No predicate pushdown on individual keys
This makes queries like SELECT ext_map['usage'] FROM metrics WHERE ext_map['usage'] > 30 scan the entire MAP column — extremely inefficient when only 1–3 keys out of thousands are needed per query.
The PIP-43: Columnar Storage Optimization for MAP Type in Paimon proposes a new shared-shredding storage layout that stores MAP values in K reusable physical columns within a Struct, achieving near-full columnar access with per-key statistics and predicate pushdown — without changing the logical type (MAP<STRING, T>).
Solution
Physical Layout
Each MAP<STRING, T> column configured with fields.<column>.map.storage-layout = shared-shredding is physically stored as:
STRUCT<
__field_mapping: FixedSizeList<Int32, K>, -- per-row: which field_id each col holds
__col_0: T, __col_1: T, ..., __col_{K-1}: T, -- reusable typed columns
__overflow: MAP<INT32, T> -- rare fallback for rows with > K fields
>
fields.<column>.map.shared-shredding.max-columns controls K_max, and fields.<column>.map.shared-shredding.column-placement-policy controls column placement.
File metadata (footer) stores: field name↔id dictionary, field_id→physical column set S, overflow set O, K, and max row width.
Write Path
-
Schema conversion utilities — Logical MAP → physical Struct schema rewriting; metadata serialization/deserialization; shared-shredding column detection via field metadata marker.
-
FormatWriter::AddMetadata— New virtual method (default no-op) for writing key-value metadata to file footer beforeFinish(). Parquet implementation callsAddKeyValueMetadata. -
Column allocator — Per-row slot allocator that maps field IDs to up to
Kphysical columns and sends the rest to overflow. Placement policy is configurable (plain,sequential,lru; defaultplain). Accumulates file-level statistics (S, O, max row width). -
Logical→physical batch converter — Parses logical MAP, encodes field names to integer IDs (file-level dictionary), invokes allocator per row, assembles physical Struct array.
-
Writer integration — Extended DataFileWriter that performs conversion before writing + injects metadata on close. AppendOnlyWriter detects shared-shredding columns and routes accordingly. Cross-file K adaptation (P99 of recent max row widths, capped by K_max).
Read Path
-
File metadata parsing — Parse shared-shredding metadata from file footer (dictionary, S, O, K). New
GetFileKeyValueMetadata()method onFileBatchReaderwith Parquet implementation. -
Predicate translation — Translate logical predicates on MAP keys into conservative OR predicates over physical sub-columns. Requires extending
LeafPredicateto support nested field paths and updatingPredicateConverterto emit nestedFieldRef. -
Read planning — At
SetReadSchematime: look up which physical columns to read (from S), decide whether__overflowis needed (from O), translate predicates, and pass the physical schema + physical predicate down to the innerFileBatchReaderunchanged. -
Batch reconstruction — After
NextBatch: read__field_mappingper row to identify which column holds which field (fine-grained filter), gather values into logicalMAP<STRING, T>. Merge overflow when needed. Correctness relies on per-row__field_mapping, not on pushdown precision. -
Reader integration — A wrapper reader (implements
FileBatchReader) sits between the upper layer and the format-level reader. Per-file instance. Compatible with varying K across files. Orthogonal toDataEvolutionFileReader(schema evolution).
Anything else?
No response
Are you willing to submit a PR?
- I'm willing to submit a PR!
- 主要语言
- C++
- 星标
- 65
- 派生
- 29
- 平均合并
- 2 天 4 小时
- 30 天内合并 PR
- 78
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
apache/paimon-cpp 的其他 Issue
-
enhancement
apache/paimon-cpp#381 · 已指派 1 人 ·
-
难度 4/5 3-5 天 新手友好度 30/100
apache/paimon-cpp#375 · 已指派 1 人 ·
-
enhancement
难度 5/5 一周以上 新手友好度 45/100
apache/paimon-cpp#361 · 已指派 1 人 ·
-
enhancement
难度 4/5 3-5 天 新手友好度 45/100
apache/paimon-cpp#325 · 已指派 1 人 ·
-
enhancement
难度 5/5 一周以上 新手友好度 35/100
apache/paimon-cpp#319 · 1 个 reaction · 已指派 1 人 ·
查看 apache/paimon-cpp 的全部 Issue
相似的 Issue
-
ai_reviewed
难度 2/5 1-3 小时 新手友好度 68/100
ydb-platform/ydb#53869 · 3 条评论 ·
-
bug cert blocker needs triage
难度 2/5 1-3 小时 新手友好度 82/100
project-chip/connectedhomeip#74373 ·
-
upstream update
难度 2/5 1-3 小时 新手友好度 75/100
conan-io/conan-center-index#31035 ·
-
Bug
难度 2/5 1-3 小时 新手友好度 68/100
-
documentation
难度 1/5 1 小时以内 新手友好度 85/100
vllm-project/vllm-ascend#17329 ·