Skip to content

GH-430: [Format] Add FINITE_VECTOR logical type with LIST storage - #624

Merged
pitrou merged 16 commits into
apache:masterfrom
rok:vector-option-c1-list
Nov 10, 2026
Merged

pitrou merged 16 commits into
apache:masterfrom
rok:vector-option-c1-list

Conversation

@rok

@rok rok commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Rationale for this change

Discussion on the ML led to a decision to split the logical annotation proposal from the original proposal, which also aimed to provide a physical representation. This PR proposes the logical annotation only, to address the need for a logical vector type.

Naming: the annotation is called FINITE_VECTOR (previously VECTOR in this PR) so that the name carries the contract: fixed length, non-null and finite elements. This leaves VECTOR available should a future proposal introduce a more general vector type or a dedicated physical representation.


This adds a FINITE_VECTOR logical type stored as a canonical 3-level LIST structure. This is a contract on top of LIST, not a new physical representation:

  1. Each non-null vector contains exactly num_elements elements.
  2. Elements are required (non-null) and finite (no NaN, +Inf or -Inf).
  3. Elements are numeric or boolean Parquet primitives.
<vector-repetition> group <name> (FINITE_VECTOR(<num_elements>)) {
  repeated group list {
    required <element-type> element;
  }
}
  • Element types: BOOLEAN, INT32/INT64 (plain, INT or DECIMAL), FLOAT, DOUBLE, FLOAT16 and FLBA DECIMAL. No nested elements.
  • Writers must enforce the element count, non-null and finite guarantees. Readers may rely on them without validating.
  • Levels, pages, encodings, statistics and bloom filters are those of the element column in an ordinary LIST. No statistics are defined for whole vectors.
  • Writers set ConvertedType.LIST alongside LogicalType.FINITE_VECTOR. Readers that fall back to the converted type read an ordinary LIST; readers that ignore both annotations see an unannotated group with a single repeated child group.

Trade-offs:

  • Repetition/definition levels are still written. Reader and writer efficiency is left to the implementations.
  • Adding new float types (e.g. FP8, BF16) requires adding a primitive Parquet type. Packed FLBA(num_elements * type_width) storage would decouple this, at the cost of element-level encodings.

Out of scope:

  • Vector indexes, quantisation and normalisation guarantees. Those need their own annotations rather than parameters on FiniteVectorType.
  • A more efficient physical type for storing fixed-sized lists may be proposed in the future and this logical type may be able to annotate it. This is intentionally left out of this proposal.

What changes are included in this PR?

Specifies the FINITE_VECTOR logical type, its LIST representation, writer/reader requirements and element-level requirements.

Do these changes have PoC implementations?

Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread src/main/thrift/parquet.thrift Resolved
Comment thread src/main/thrift/parquet.thrift Resolved
Comment thread src/main/thrift/parquet.thrift Resolved
@HuaHuaY

HuaHuaY commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Sorry I haven't followed VECTOR type progress in a while. Why was Option B mentioned in the email from May eliminated? I see that only Option A and Option C1 are left in the email from September.

@rok

rok commented Sep 23, 2026

Copy link
Copy Markdown
Member Author

Option B mentioned in the email from May eliminated? I see that only Option A and Option C1 are left in the email from September.

Thanks for the question @HuaHuaY ! Option B requires changes to physical layout of data - either via new repetition level or another mechanism. As logical and physical changes are somewhat independent and should likely both be done, we decided to propose them separately. So in short Option B is not eliminated, only delayed until logical type for vectors is settled. Apologies this was not clear from my communication.

@alamb alamb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposal seems pretty good to me -- I think there are some places where we could reduce its size and make it more concise, but the high level idea looks good

Comment thread src/main/thrift/parquet.thrift Resolved
Comment thread LogicalTypes.md Resolved
Comment thread src/main/thrift/parquet.thrift Resolved
Comment thread src/main/thrift/parquet.thrift Resolved
Comment thread LogicalTypes.md Resolved
Comment thread src/main/thrift/parquet.thrift Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved

@divjotarora divjotarora left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small wording comments, but overall LGTM. Thanks for driving this @rok!

Comment thread src/main/thrift/parquet.thrift Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
@PFischbeck PFischbeck mentioned this pull request Sep 28, 2026
1 of 6 tasks

@PFischbeck PFischbeck left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good to me!

Comment thread src/main/thrift/parquet.thrift Resolved
Comment thread src/main/thrift/parquet.thrift Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread src/main/thrift/parquet.thrift Resolved
rok added 6 commits October 30, 2026 12:29
Co-authored-by: Rok Mihevc <rok@mihevc.org>
Co-authored-by: Rok Mihevc <rok@mihevc.org>
Co-authored-by: Rok Mihevc <rok@mihevc.org>
Co-authored-by: Rok Mihevc <rok@mihevc.org>
@rok
rok force-pushed the vector-option-c1-list branch from ac3438d to 2bdc543 Compare October 30, 2026 11:37
@rok
rok force-pushed the vector-option-c1-list branch from 268ab40 to daac474 Compare October 30, 2026 11:52
@rok
rok force-pushed the vector-option-c1-list branch from 97fb091 to 6c9f73e Compare October 30, 2026 11:56
@rok

rok commented Nov 1, 2026

Copy link
Copy Markdown
Member Author

Hey @JigaoLuo thanks for reviewing! Discussion on points you raise would better fit the discusson on the ML (1, 2). I'll still try to reply here, but if you want to push this further the dev@parquet ML is the platform you should use.

there is other metadata that would make vector data more self-describing. It could live in Parquet or in Iceberg:

  1. Distance function. See the reasoning from Harsha and the related discussion on the Iceberg side: https://docs.google.com/document/d/1zA8PskNDFKXXJpzWQr25CFoX_aIZHBNHbkxk0t3PteE/edit?disco=AAACDqu3oWI&pli=1

I am not an embeddings or vector DB expert, but wouldn't distance metric always an operation acting on pairs of vectors? It feels more like an application level concern and parquet already has a file-level metadata key-value metadata where such information could be stored. Or am I missing something here that could not be captured there?

  1. Lineage: which embedding model or API produced the vectors.

Agreed that this is important information, but I'm not sure it's something that should live in the type. It would make parquet more self-contained, but it would require agreement on model identity between embedding producers which is out of reach for parquet. If you feel strongly about this, please sketch out how you imagine this would look like.

@JigaoLuo

JigaoLuo commented Nov 2, 2026

Copy link
Copy Markdown

Hi @rok Thanks for sharing these. I'll go through the two discussions.

It feels more like an application level concern and parquet already has a file-level metadata key-value metadata where such information could be stored.

On point 1, I think this is a good place for it.

Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved

@alamb alamb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good to me. I left some suggestions to cut it down more, but I don't think any other changes are needed (other than what @pitrou has suggested)

Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
Comment thread LogicalTypes.md Resolved
@rok
rok force-pushed the vector-option-c1-list branch 2 times, most recently from 7c67461 to 81bc323 Compare November 4, 2026 18:38
Co-authored-by: Antoine Pitrou <pitrou@free.fr>
@rok
rok force-pushed the vector-option-c1-list branch from 81bc323 to 70b3023 Compare November 4, 2026 18:41
Comment thread LogicalTypes.md
}
```

### Finite Vectors

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧑‍🍳 👌

Comment thread LogicalTypes.md
* unannotated `BOOLEAN`, `FLOAT` or `DOUBLE`
* `INT32` or `INT64`, either unannotated or annotated with `INTEGER` or
`DECIMAL`
* `FIXED_LEN_BYTE_ARRAY` annotated with `FLOAT16` or `DECIMAL`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious if BYTE_ARRAY annotated with DECIMAL should be supported.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For completeness, it could be added, but I'd leave it out. Every supported element type is fixed width. Any decimal precision can already be stored as FIXED_LEN_BYTE_ARRAY, so excluding BYTE_ARRAY loses nothing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed width allows for some optimizations that variable width doesn't. I believe allowing variable-width types would make writers more complex as they'd have to enable or disable these optimizations at write time.
If it turns out there's a need for this we can revisit later too!

Comment thread LogicalTypes.md
* unannotated `BOOLEAN`, `FLOAT` or `DOUBLE`
* `INT32` or `INT64`, either unannotated or annotated with `INTEGER` or
`DECIMAL`
* `FIXED_LEN_BYTE_ARRAY` annotated with `FLOAT16` or `DECIMAL`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For completeness, it could be added, but I'd leave it out. Every supported element type is fixed width. Any decimal precision can already be stored as FIXED_LEN_BYTE_ARRAY, so excluding BYTE_ARRAY loses nothing.

@pitrou
pitrou merged commit ec90dd4 into apache:master Nov 10, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.