blob: 6fd5c41b23127dfdb77d0c7c48a1d38fd93c03e4 [file]
.. Licensed to the Apache Software Foundation (ASF) under one
.. or more contributor license agreements. See the NOTICE file
.. distributed with this work for additional information
.. regarding copyright ownership. The ASF licenses this file
.. to you under the Apache License, Version 2.0 (the
.. "License"); you may not use this file except in compliance
.. with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
.. software distributed under the License is distributed on an
.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
.. KIND, either express or implied. See the License for the
.. specific language governing permissions and limitations
.. under the License.
Write
=====
Batch writing requires the compute engine to specify the target ``partition``.
For fixed-bucket tables, the engine must also assign a valid bucket to every
``RecordBatch``. In unaware-bucket and postpone-bucket modes, the writer can
resolve the bucket automatically when it is omitted.
Paimon C++ uses Apache Arrow as the :ref:`in-memory columnar format<memory-format>`
to more efficiently support writing to disk columnar formats such as ORC,
Parquet, and Avro, thereby improving write throughput.
.. note::
Currently supported table types:
- Append table
- Primary Key table
Not supported in the current scope:
- Changelog
Bucketing Modes
---------------
- Append tables:
* Support ``bucket = -1`` (unaware-bucket mode)
* Support ``bucket > 0`` (fixed bucket mode)
- PK tables:
* Support ``bucket = -2`` (postpone bucket mode)
* Support ``bucket > 0`` (fixed bucket mode)
.. note::
PK tables do not support dynamic bucketing (``bucket = -1``).
RecordBatch Construction
------------------------
- The compute engine must:
- Assign the correct ``partition`` for each row.
- In fixed-bucket mode, apply the Paimon-consistent bucketing function, set a
bucket in ``[0, bucket)``, and group rows into Arrow ``RecordBatch`` objects
per partition-bucket combination.
- In unaware-bucket mode (append table with ``bucket = -1``), an omitted bucket
is resolved to ``0``.
- In postpone-bucket mode (primary-key table with ``bucket = -2``), an omitted
bucket is resolved to ``-2``.
- Recommended practices:
- Use schema-aligned Arrow arrays with explicit validity bitmaps and offsets.
- Prefer batch sizes tuned for I/O throughput (e.g., tens to hundreds of MB per flush, depending on filesystem and cluster configuration).
- Maintain stable sort orders within a batch only if required by downstream merge or compaction logic; otherwise avoid unnecessary ordering costs.
Prepare Commit
----------------
The compute engine is responsible for triggering the writer nodes' ``PrepareCommit``.
Triggering conditions depend on the engine's business needs and can follow either:
- Streaming mode: time-based or periodic triggers (e.g., every N seconds).
- Batch mode: trigger after all data in the batch has been written.
Once the compute engine collects ``CommitMessages`` from all writer nodes, it
can issue a ``Commit`` request to the control plane (management path) to create
a new ``Snapshot``.
Compatibility Goals
~~~~~~~~~~~~~~~~~~~
To ensure interoperability, the ``PrepareCommit`` result produced by Paimon C++
must be consumable by Paimon Java. Therefore:
- The structure and semantics of ``CommitMessage`` must remain consistent with
Java Paimon.
- Any evolution of the Java-side ``CommitMessage`` schema must be tracked and
validated on the C++ side to maintain cross-language compatibility.
Interface Design in Paimon C++
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlike Java Paimon, Paimon C++ does not expose ``BinaryRow``-like types in its
public interfaces. To preserve compatibility without leaking internal row
representations, Paimon C++ provides ``CommitMessage`` only through:
- Serialization: convert the internal commit state into a well-defined binary
representation that matches Java Paimon's expectations.
- Deserialization: parse the Java-compatible binary representation back into
C++ commit structures for validation, replay, or tooling needs.
This design ensures that:
- Public APIs are independent of Java-specific row abstractions.
- Cross-language commit payloads remain stable and versionable.
- Internal data layouts can evolve without breaking external consumers.
CommitMessage Contract
~~~~~~~~~~~~~~~~~~~~~~
The ``CommitMessage`` must encode all information required by the coordinator to
produce a correct ``Snapshot``, which commonly includes (but is not limited to):
- Partition and bucket identifiers associated with written data.
- New data files, delete files (as applicable to the table type).
- File-level metadata required for manifest and index updates (e.g., row counts, min/max statistics where applicable).
- Transactional markers and sequence numbers as required by table semantics.
- Any per-writer state necessary for deduplication or idempotent commits.
.. note::
The C++ writer supports Append and PK tables and can produce
``CommitMessage`` objects for both. ``FileStoreCommit`` currently executes
local commits only for append-only tables on non-object-store file systems.
PK and object-store commit messages must be sent to an external control
plane. Changelog is out of scope and should not be emitted in
``CommitMessage`` until explicitly supported.
Serialization and Deserialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- **Binary format:** The binary payload must strictly conform to Java Paimon's
``CommitMessage`` encoding. It does not contain a version tag, so callers
must transport ``CommitMessage::CurrentVersion()`` separately and supply it
when deserializing.
- **Serialization API:** Use ``CommitMessage::Serialize`` for one message or
``CommitMessage::SerializeList`` for a list.
- **Deserialization API:** Use ``CommitMessage::Deserialize`` or
``CommitMessage::DeserializeList`` with the separately supplied
serialization version.
- **Validation:** Conformance and round-trip tests must verify compatibility
with Java Paimon for supported message versions.
Operational Flow
~~~~~~~~~~~~~~~~~~~~~~~
1. Writer nodes perform data ingestion and produce Arrow ``RecordBatch``
organized by partition and bucket.
2. Writers flush batches into ORC/Parquet files via registered ``file.format``
and ``file-system`` backends, producing file-level metadata and per-batch
commit state.
3. Each writer invokes ``PrepareCommit``, which:
- Aggregates per-writer state into a ``CommitMessage``.
- Returns ``CommitMessage`` objects; it does not serialize them.
4. The compute engine gathers ``CommitMessage`` objects from all writers. For
cross-process transport, it explicitly calls ``Serialize`` or
``SerializeList`` and carries ``CurrentVersion()`` alongside the payload.
5. For a supported local append-table commit, the engine passes the objects to
``FileStoreCommit``. For PK tables or object-store paths, it sends the
serialized payload and version to an external control plane.
6. The local committer or external coordinator validates the messages, updates
manifests/metadata, and finalizes the snapshot atomically.