Skip to main content

File Format

Paimon stores records in files using the configured file.format. Parquet is the default. Choose a format supported by your table features and the engines that will read the table.

Use this page for format-specific type mappings and configuration. The Data Files specification describes the surrounding partition, bucket, and record layout; Data Types describes Paimon's logical types.

FormatReference
ParquetDefault columnar format and type mappings
AvroRow-oriented format and type mappings
ORCColumnar format and type mappings
CSVDelimited text and type mappings
TextText records and line delimiters
JSONJSON records and type mappings
LanceFormat integration for ML and vector workloads
VortexColumnar format integration
MosaicColumn bucketing for wide tables
RowRow-oriented blocks with row-number lookup; see the binary specification
BLOBBinary-object storage and video handling

Parquet​

Parquet is the default file format for Paimon.

The following table lists the type mapping from Paimon type to Parquet type.

Paimon TypeParquet typeParquet logical type
CHAR / VARCHAR / STRINGBINARYUTF8
BOOLEANBOOLEAN
BINARY / VARBINARYBINARY
GEOMETRY(crs)BINARYGEOMETRY(crs)
GEOGRAPHY(crs, algorithm)BINARYGEOGRAPHY(crs, algorithm)
DECIMAL(P, S)P <= 9: INT32, P <= 18: INT64, P > 18: FIXED_LEN_BYTE_ARRAYDECIMAL(P, S)
TINYINTINT32INT_8
SMALLINTINT32INT_16
INTINT32
BIGINTINT64
FLOATFLOAT
DOUBLEDOUBLE
DATEINT32DATE
TIMEINT32TIME_MILLIS
TIMESTAMP(P)P <= 3: INT64, P <= 6: INT64, P > 6: INT96P <= 3: MILLIS, P <= 6: MICROS, P > 6: NONE
TIMESTAMP_LOCAL_ZONE(P)P <= 3: INT64, P <= 6: INT64, P > 6: INT96P <= 3: MILLIS, P <= 6: MICROS, P > 6: NONE
ARRAY3-LEVEL LISTLIST
MAP3-LEVEL MAPMAP
MULTISET3-LEVEL MAPMAP
ROWGROUP

Limitations:

  1. Parquet does not support nullable map keys.
  2. Parquet TIMESTAMP type with precision 9 will use INT96, but this int96 is a time zone converted value and requires additional adjustments.
  3. Tables containing GEOMETRY or GEOGRAPHY columns must use Parquet for file.format, every entry in file.format.per.level, and changelog-file.format when configured.

Avro​

The following table lists the type mapping from Paimon type to Avro type.

Paimon typeAvro typeAvro logical type
CHAR / VARCHAR / STRINGstring
BOOLEANboolean
BINARY / VARBINARYbytes
DECIMALbytesdecimal
TINYINTint
SMALLINTint
INTint
BIGINTlong
FLOATfloat
DOUBLEdouble
DATEintdate
TIMEinttime-millis
TIMESTAMPP <= 3: long, P <= 6: long, P > 6: unsupportedP <= 3: timestampMillis, P <= 6: timestampMicros, P > 6: unsupported
TIMESTAMP_LOCAL_ZONEP <= 3: long, P <= 6: long, P > 6: unsupportedP <= 3: localTimestampMillis, P <= 6: localTimestampMicros, P > 6: unsupported
ARRAYarray
MAPstring/char/varchar key: map
other key: array of key-value record
other key: map
MULTISETstring/char/varchar element: map
other element: array of element-count record
other element: map
ROWrecord

Note:

In addition to the types listed above, for nullable types. Paimon maps nullable types to Avro union(something, null), where something is the Avro type converted from Paimon type.

You can refer to Avro Specification for more information about Avro types.

ORC​

The following table lists the type mapping from Paimon type to Orc type.

Paimon TypeOrc physical typeOrc logical type
CHARbytesCHAR
VARCHARbytesVARCHAR
STRINGbytesSTRING
BOOLEANlongBOOLEAN
BYTESbytesBINARY
DECIMALdecimalDECIMAL
TINYINTlongBYTE
SMALLINTlongSHORT
INTlongINT
BIGINTlongLONG
FLOATdoubleFLOAT
DOUBLEdoubleDOUBLE
DATElongDATE
TIMESTAMPtimestampTIMESTAMP
TIMESTAMP_LOCAL_ZONEtimestampTIMESTAMP_INSTANT
ARRAY-LIST
MAP-MAP
ROW-STRUCT

Limitations:

  1. ORC has a time zone bias when mapping TIMESTAMP_LOCAL_ZONE type, saving the millis value corresponding to the UTC literal time. Due to compatibility issues, this behavior cannot be modified.

CSV​

Experimental feature, not recommended for production.

Format Options:

OptionDefaultTypeDescription
csv.field-delimiter,StringField delimiter character (',' by default), must be single character. You can use backslash to specify special characters, e.g. '\t' represents the tab character.
csv.line-delimiter\nStringThe line delimiter for CSV format
csv.quote-character"StringQuote character for enclosing field values (" by default), must be single character.
csv.escape-character\StringThe escape character for CSV format, must be single character.
csv.include-headerfalseBooleanWhether to include header in CSV files.
csv.null-literal""StringNull literal string that is interpreted as a null value (disabled by default).
csv.modePERMISSIVEStringAllows a mode for dealing with corrupt records during reading. Currently supported values are 'PERMISSIVE', 'DROPMALFORMED' and 'FAILFAST':
  • Option 'PERMISSIVE' sets malformed fields to null.
  • Option 'DROPMALFORMED' ignores the whole corrupted records.
  • Option 'FAILFAST' throws an exception when it meets corrupted records.

Paimon CSV format uses jackson databind API to parse and generate CSV string.

The following table lists the type mapping from Paimon type to CSV type.

Paimon typeCSV type
CHAR / VARCHAR / STRINGstring
BOOLEANboolean
BINARY / VARBINARYstring with encoding: base64
DECIMALnumber
TINYINTnumber
SMALLINTnumber
INTnumber
BIGINTnumber
FLOATnumber
DOUBLEnumber
DATEstring with format: date
TIMEstring with format: time
TIMESTAMPstring with format: date-time
TIMESTAMP_LOCAL_ZONEstring with format: date-time

Text​

Experimental feature, not recommended for production.

Format Options:

OptionDefaultTypeDescription
text.line-delimiter\nStringThe line delimiter for TEXT format

The Paimon text table contains only one field, and it is of string type.

JSON​

Experimental feature, not recommended for production.

Format Options:

OptionDefaultTypeDescription
json.ignore-parse-errorsfalseBooleanWhether to ignore parse errors for JSON format. Skip fields and rows with parse errors instead of failing. Fields are set to null in case of errors.
json.map-null-key-modeFAILStringHow to handle map keys that are null. Currently supported values are 'FAIL', 'DROP' and 'LITERAL':
  • Option 'FAIL' will throw exception when encountering map with null key.
  • Option 'DROP' will drop null key entries for map.
  • Option 'LITERAL' will replace null key with string literal. The string literal is defined by json.map-null-key-literal option.
json.map-null-key-literalnullStringLiteral to use for null map keys when json.map-null-key-mode is LITERAL.
json.line-delimiter\nStringThe line delimiter for JSON format.

Paimon JSON format uses jackson databind API to parse and generate JSON string.

The following table lists the type mapping from Paimon type to JSON type.

Paimon typeJSON type
CHAR / VARCHAR / STRINGstring
BOOLEANboolean
BINARY / VARBINARYstring with encoding: base64
DECIMALnumber
TINYINTnumber
SMALLINTnumber
INTnumber
BIGINTnumber
FLOATnumber
DOUBLEnumber
DATEstring with format: date
TIMEstring with format: time
TIMESTAMPstring with format: date-time
TIMESTAMP_LOCAL_ZONEstring with format: date-time (with UTC time zone)
ARRAYarray
MAPobject
ROWobject

Lance​

Lance is a modern columnar data format optimized for machine learning and vector search workloads. It provides high-performance read and write operations with native support for Apache Arrow.

The following table lists the type mapping from Paimon type to Lance (Arrow) type.

Paimon TypeLance (Arrow) type
CHAR / VARCHAR / STRINGUTF8
BOOLEANBOOL
BINARY / VARBINARYBINARY
DECIMAL(P, S)DECIMAL128(P, S)
TINYINTINT8
SMALLINTINT16
INTINT32
BIGINTINT64
FLOATFLOAT
DOUBLEDOUBLE
DATEDATE32
TIMETIME32 / TIME64
TIMESTAMP(P)TIMESTAMP (unit based on precision)
ARRAYLIST
ROWSTRUCT

Limitations:

  1. Lance file format does not support MAP, MULTISET, TIMESTAMP_LOCAL_ZONE or VARIANT types.
  2. Lance file format does not support BLOB fields stored inline in data files (blob-descriptor-field or blob-view-field). Regular BLOB fields are written to dedicated blob files and are not affected.

Vortex​

Vortex is a columnar file format that uses adaptive, data-dependent encodings to achieve high compression ratios while maintaining fast scan performance. It supports native predicate pushdown and efficient column projection.

Key features:

  • Adaptive Encoding: Automatically selects the best encoding per column based on data distribution
  • Native Predicate Pushdown: Supports filter expressions pushed down to the scan layer
  • Column Projection: Only reads requested columns from disk

Limitations:

  1. Vortex does not support MAP, MULTISET or VARIANT types.
  2. Vortex does not support BLOB fields stored inline in data files (blob-descriptor-field or blob-view-field). Regular BLOB fields are written to dedicated blob files and are not affected.

Mosaic​

Mosaic is a columnar-bucket hybrid format optimized for wide tables. It groups columns into buckets and compresses each bucket independently with ZSTD, enabling efficient column projection that only reads the buckets containing requested columns.

Key features:

  • Column Bucketing: Columns are grouped into configurable buckets for parallel I/O, significantly reducing read amplification on wide tables
  • Row Group Statistics: Per-row-group min/max/null_count statistics enable row group skipping during scan
  • ZSTD Compression: All data is compressed with ZSTD (configurable level)
  • Arrow-native: Uses Apache Arrow as the in-memory representation for zero-copy integration

Format Options:

OptionDefaultTypeDescription
mosaic.num-bucketsautoIntegerNumber of column buckets for parallel I/O. When set to 0 or not specified, the format auto-determines the bucket count.
mosaic.stats-columns(empty)StringComma-separated column names to collect min/max statistics for filter pushdown. Empty means no statistics are collected.
mosaic.read.prefetch-row-groups8IntegerNumber of row groups a reader opens ahead of the one being consumed. Opening a row group issues several dependent range reads, so prefetching overlaps that latency with decoding. Each row group ahead keeps its decoded batch in memory and uses its own input stream, see mosaic.read.prefetch-max-bytes. 0 disables prefetching.
mosaic.read.prefetch-max-bytes64 mbMemorySizeUpper bound on the estimated decoded size of the row groups a reader keeps ahead, from their row counts and the projected column types. Wide projections or large row groups therefore lower the effective mosaic.read.prefetch-row-groups.

Limitations:

  1. Mosaic does not support complex types: ARRAY, MAP, MULTISET, ROW, VARIANT, BLOB, VECTOR.

For more details, see the Mosaic documentation.

Row​

The Row format stores complete rows in independently compressed ZSTD blocks. Each decompressed block contains a row-offset array for direct positioning. The compression level defaults to 1 and is configured with file.compression.zstd-level.

  • Row positioning: locating a row within a decompressed block is O(1); selecting and loading its block adds index, I/O, and decompression work.
  • Compact encoding: a null bitmap precedes sequentially encoded field values.
  • Row selection: the reader selects blocks and rows from requested row positions, avoiding decompression of unselected blocks. Vectored I/O can still read intervening bytes.

For field encodings, projection behavior, and configuration, see Row Format.

BLOB​

The BLOB format is a specialized format for storing large binary objects such as images, videos, and other multimodal data. Unlike other formats that store data inline, BLOB format stores large binary data in separate files with an optimized layout for random access.

BLOB files use the .blob extension and have the following structure:

+------------------+
| Blob Entry 1 |
| Magic Number | 4 bytes (1481511375, Little Endian)
| Blob Data | Variable length
| Length | 8 bytes (Little Endian)
| CRC32 | 4 bytes (Little Endian)
+------------------+
| Blob Entry 2 |
| ... |
+------------------+
| Index | Variable (Delta-Varint compressed)
+------------------+
| Index Length | 4 bytes (Little Endian)
| Version | 1 byte
+------------------+

Each physical BLOB file stores one logical field. The field can be BLOB, ARRAY<BLOB>, or MAP<K, BLOB>. For ARRAY<BLOB>, the variable-length data area in an entry uses the following nested payload:

+----------------------+-----------------------------------------------+
| Array Magic Number | 4 bytes (1094861634, Little Endian) |
| Array Version | 1 byte |
| Element Count | 4 bytes (Little Endian) |
| Element Data | Concatenated bytes of all non-null elements |
| Element Length Index | Delta-Varint compressed element lengths |
| Index Length | 4 bytes (Little Endian) |
+----------------------+-----------------------------------------------+

An element length of -1 represents a null array element. An empty array is encoded with an element count of zero and an empty element index; it is distinct from a null array.

For MAP<K, BLOB>, the variable-length data area uses the following nested payload:

+----------------------+-----------------------------------------------+
| Map Magic Number | 4 bytes (1296188226, Little Endian) |
| Map Version | 1 byte |
| Entry Count | 4 bytes (Little Endian) |
| Key Data | Concatenated bytes of all non-null keys |
| Blob Data | Concatenated bytes of all non-null values |
| Key Length Index | Delta-Varint compressed key lengths |
| Blob Length Index | Delta-Varint compressed Blob lengths |
| Key Index Length | 4 bytes (Little Endian) |
| Blob Index Length | 4 bytes (Little Endian) |
+----------------------+-----------------------------------------------+

The key and Blob length indexes are aligned by entry position. A length of -1 represents null, while zero represents an empty key or Blob. Supported key types and their encodings are:

Key typeEncoding
TINYINT, SMALLINT, INT, BIGINTSigned integer in little-endian byte order using the type's fixed width
BOOLEANOne byte: 0 for false and 1 for true
DECIMAL(p, s), p <= 18Eight-byte little-endian signed unscaled integer
DECIMAL(p, s), p > 18Minimal-length signed big-endian two's-complement unscaled integer
DATEFour-byte little-endian signed count of days since 1970-01-01
TIME(p)Four-byte little-endian signed count of milliseconds since midnight
BINARY, VARBINARY (BYTES)Raw bytes
CHAR, VARCHARUTF-8 bytes

The DECIMAL scale is defined by the field type and is not stored in each key. BINARY and VARBINARY keys are not padded, truncated, or validated against the declared length. An empty map has an entry count of zero and is distinct from a null map. The TIME(p) encoding uses Paimon's millisecond internal representation and does not add nanosecond precision.

At the outer file index level, -1 represents a null field and -2 represents a field placeholder used by data evolution.

Key features:

  • CRC32 Checksums: Each blob entry has a CRC32 checksum for data integrity verification
  • Indexed Access: The index at the end enables efficient random access to any blob in the file
  • Delta-Varint Compression: The index uses delta-varint compression for space efficiency

Limitations:

  1. BLOB format only supports a single BLOB, ARRAY<BLOB>, or MAP<K, BLOB> field per physical file.
  2. BLOB format does not support predicate pushdown.
  3. Statistics collection is not supported for BLOB columns.

Video​

.video stores complete encoded videos and frame runs, without BLOB entry headers, length trailers, or per-entry CRC. On-disk order:

+----------------------------+
| Encoded Video Payload 1 | Raw complete video bytes
+----------------------------+
| Encoded Video Payload 2 |
+----------------------------+
| ... |
+----------------------------+
| Keyframe Index 1 | Video metadata ranges and compressed keyframe entries
+----------------------------+
| Keyframe Index 2 |
+----------------------------+
| Physical Length Index | Delta-Varint video lengths
+----------------------------+
| Keyframe-Index Length Index | Delta-Varint block lengths per video (0 = scan fallback)
+----------------------------+
| Run Length Index | Delta-Varint logical row counts
+----------------------------+
| Run Reference Index | Delta-Varint physical video ordinals
+----------------------------+
| Run First-Frame Index | Delta-Varint frame ordinals
+----------------------------+
| Physical Index Length | 4 bytes (Little Endian)
| Keyframe Length-Index Size | 4 bytes (Little Endian)
| Run-Length Index Length | 4 bytes (Little Endian)
| Run-Reference Index Length | 4 bytes (Little Endian)
| First-Frame Index Length | 4 bytes (Little Endian)
| Magic Number | 4 bytes (0x4F454449, Little Endian)
| Version | 1 byte
+----------------------------+

Run arrays have equal lengths. Non-negative references select a video; -1 means NULL and -2 means a data-evolution placeholder. Row r in a run starting at s maps to frame run_first_frame + r - s; gaps start new runs.

A keyframe-index block contains a 17-byte header (version 1: uint8; magic 0x564944454F4B4649: uint64; metadata-range and keyframe counts: uint32 each), metadata (offset, length) pairs (int64 each), and zlib-compressed (frame ordinal, PTS, packet position) entries (int64 each). Numeric fields are little endian; offsets are payload-relative. Limits: 65,536 metadata ranges and 65,536 keyframes, 16 MiB per block, 64 MiB per file. The index covers the first video stream; its time base stays in the video.

An Arrow/data-file cell stores a separately versioned, little-endian VideoFrameDescriptor:

FieldSizeDescription
Version1 byteDescriptor version, currently 1
Magic8 bytes0x564944454F46524D (VIDEOFRM)
URI length4 bytesUTF-8 URI byte length
URIvariableURI of the containing .video file
Offset8 bytesStart of the complete encoded-video payload
Length8 bytesEncoded-video payload length
Frame index8 bytesZero-based presentation-order frame ordinal
Keyframe-index offset8 bytesIndex offset in the .video file, or -1
Keyframe-index length8 bytesIndex length, or 0

A .video file serves one scalar BLOB field; references are file-local. .blob is unchanged.

For usage details, configuration options, and examples, see Blob Type.