はじめに
AIモデルの学習やRAGの構築には、画像や音声、埋め込みベクトルといったデータをどこにどう置くかという、データ基盤側の話が一緒についてきます。
分析用に整えてきたレイクハウスにそのまま載せるのか、AIワークロード向けに設計されたフォーマットを別に用意するのか。
この記事で扱うLance formatは、後者にあたるオープンなデータフォーマットです。
この記事では、AIワークロードがデータ基盤に求める読み書きをApache Icebergの設計の前提と比べ、Lance formatがどこを別の設計にしたのかを整理しています。
あわせて、その上に作られたLanceDBの役割も見ていきます。
公式ドキュメントと論文をもとに、自分なりの解釈も含めて整理したものです。
Oracle公式の見解ではありません。
AIワークロードで扱うデータと、求められる読み書き
まず、AIのワークロードがデータ基盤に何を求めるのかを、「扱うデータ」と「読み書き」の2つの視点から確認します。
ここでいうデータ基盤は、オブジェクトストレージ上のオープンなファイル形式にデータウェアハウスの管理機能を載せる「レイクハウス」の構成です1。
データの視点から見ると、画像、音声、動画、文書といったファイルに加えて、埋め込みベクトルが1行の中の1列として並びます。
埋め込みベクトルは数百から数千個の浮動小数点数の並びで、意味の近さを数値の距離として比べるために使います。
1行の大きさも表形式のデータより大きく、768次元のfloat32の埋め込みだけで約3KB、画像を持てば数百KBから数MBになります。
読み書きの視点では、必要な列だけを絞って多数の行をまとめて読む分析のクエリに、主に次のような読み書きが加わります。
- 学習データのシャッフル — 深層学習の学習では、学習データ全体を1回通す単位(エポック)ごとに繰り返し読み、1エポックの中ではランダムな順序で読む2
- 検索での少数行の取り出し — ベクトル検索では、クエリに近い上位数十件の行だけを取り出す。行は主キーの順に並んでいないので、行ごとに離れた場所を読むランダムアクセスになる3
- 列の追加 — 新しいモデルで計算し直した埋め込みやラベル、スコアの列を、既存のすべての行に後から足す
- 版の固定 — どの時点のデータで学習したのかを再現できるよう、データのバージョンを固定する
左の分析では1つの列を上から下まで読み、右のAIワークロードでは離れた行を1行ずつ取り出し、列を後から足します。
Apache Icebergの設計の前提
比較対象となるApache Icebergが何を前提に設計されているかを確認します。
仕様書では、Icebergについて「分散ファイルシステムやキーバリューストア上の、大きくて変化の遅いファイルの集まりを、テーブルとして管理するための仕様」と説明しています4。
この前提のもとでIcebergが管理する単位はファイルで、仕様にも「一度書かれたデータファイルとメタデータファイルは、削除されるまで不変である」とあります4。
カタログからメタデータファイル、マニフェストリスト、マニフェストとたどって、データファイルの一覧に行き着く構成です。
一方で、ファイルの中身をどう並べ、どう1行を取り出すかは、Icebergの管理の外で、データファイルの形式の側の話です。
以下では、その形式にParquetを使う構成を考えます。
破線の枠の中がIcebergの管理する範囲で、データファイルの中身の並べ方はParquetの側にあります。
(Icebergの各要素の役割は、以前の記事で整理しています。)
Parquet+Icebergの構成に残る課題
Icebergがファイル単位で管理し、中身はParquetに任せるという役割分担に、
AIワークロードのデータと読み書きを当てはめると、主に次の4か所に課題が見えてきます。
(「版の固定」は、Icebergのスナップショットがそのまま使えるので、課題とはなりません。)
1行を取り出すときの読み取り量
1つ目は、1行を取り出すときに読む量です。、Parquetファイルの内部構造で決まります。
Parquetファイルは、テーブルの行を多数の行ずつのまとまりである行グループに切り、行グループの中ではデータを列ごとの列チャンクに分けて置きます5。
列チャンクはさらにページという小さなかたまりに分かれ、1つのページにはその列の連続する行の値がまとめて入っています。
圧縮と符号化はこのページを単位に行われ、仕様書もページを「分割できない単位」と説明しています。
そのため、1行だけが欲しいときでも、その行の値を含むページを列ごとに読み込み、ページ全体の圧縮を解いてから目的の値を取り出すことになります。
行グループの大きさも、埋め込みや画像のような大きい値の列があると決めにくくなります。
ファイル全体で1つしか選べず、小さい値の列には大きな行グループが、大きい値の列には小さな行グループが向くためです3。
既存の行に列の値を足すときの書き換え
2つ目は、既存の行すべてに新しい列の値を入れるときの書き換えです。
列の定義を足すスキーマ進化は、データファイルを書き換えずに済みます。
ただし、既存の行の値として仕様が用意しているのは、列を足した時点より前の行に一定の既定値を返す仕組みです4。
行ごとに違う値を入れるには行単位の更新が必要で、copy-on-writeならデータファイルを書き直し、merge-on-readなら削除の記録と新しい行を書きます。
どちらの場合も、1列のためにその行の他の列も一緒に書かれます。
左右どちらも、赤で囲んだ既存の列が新しいファイルに書き直されています。
この書き換えについては、Icebergのコミュニティも2026年1月の提案で、更新した列だけを別のファイルに書く列単位の更新をバージョン4の検討項目に挙げています6。
ベクトルの型と索引
3つ目は、埋め込みベクトルの型と索引です。
Icebergの仕様には埋め込みベクトルのための型がなく、2025年5月に採択されたバージョン3にも入っていないため、埋め込みはfloatのlist型として保存します4。
近いベクトルを近似的に探す検索(近似最近傍検索)の索引も仕様の外で、クエリエンジンや外部のベクトルデータベースの側で設計することになります。
型については、2026年9月にバージョン4に向けたベクトル型の提案が出ています6。
画像や動画のような大きなバイナリ
4つ目は、大きなバイナリの持ち方です。
Icebergにはbinary型がありますが、Parquetのbinary値は4バイトの長さ情報に続けてバイト列を書く形式で、ページの大きさも32ビットの整数で表されるため、1つの値の上限は2GBです5。
加えて、動画のように1つの値が数百MBになるデータを行の中に持つと、その行を読むたびに値全体を含むページを読み込むことになります。
ここも動きがあり、Parquetでは2026年7月に、ファイルの中身か外部ファイルへの参照を1つの値として持つFILEという論理型が仕様に取り込まれました5。
Icebergでも2026年9月に、このFILE型に対応するファイル型をバージョン4に加える提案が出ています6。
こうした提案がIceberg側で進む一方で、AIワークロードの読み書きを前提にファイルの形式から設計し直したのがLance formatです。
Lance formatとは
Lance formatは、LanceDB社が開発を始めた、複数の種類のデータを扱うマルチモーダルAI向けのオープンなレイクハウスフォーマットで、ファイルフォーマット、テーブルフォーマット、カタログの仕様を含みます7。
この仕様を実装するLanceライブラリはApache License 2.0で、中核はRustで書かれ、PythonとJavaのバインディングがあり、型システムにはApache Arrowを使います。
以下では、先ほどの4か所の隙間にあたる部分を順に見ていきます。
ファイルフォーマット:行グループを持たない列指向
Lanceのファイルフォーマットは、Parquetと同じ列指向ですが、行グループを持ちません8。
列ごとに独立してページを区切るので、行グループの大きさをファイル全体で1つ選ぶ必要がなく、埋め込みのような大きい値の列と小さい値の列で区切りを別々に決められます。
左がParquet、右がLanceで、緑の箱が、1行を取り出すために読んで展開するページです。
ページの中では、値の大きさで並べ方を使い分けます8。
整数や短い文字列のような小さい値はミニブロックという単位(圧縮後32KiB未満)にまとめ、読むときはページ全体ではなく、そのミニブロックだけを展開します。
埋め込みのような大きい値は、値ごとに位置が決まる並べ方(full-zip)にして、1つの値だけを読みます。
Lanceの開発者による2025年の論文は、小さなスカラー値のランダムアクセスの測定で、この符号化をParquetと比べています3。
その測定では、行グループとページの設定を調整したParquetが既定の設定より大幅に速い一方、スキャン性能とメモリ使用量に小さなトレードオフが生じています。
Lanceの符号化は、その調整なしに、調整後のParquetと同等以上のランダムアクセス性能を出す、というのが論文の主張です。
こうした符号化は、ファイルフォーマットの版(2.0、2.1、2.2)ごとに加わってきたもので、この版はLanceライブラリの版とは別に管理されています8。
2026年9月のLanceライブラリ12.0.0では、2.2が既定の版です。
テーブルフォーマット:行のまとまりと、列ごとのデータファイル
Lanceでは1つのテーブルをデータセットと呼び、1つのディレクトリとして持ちます9。
版ごとのメタデータはマニフェストというファイルで、スキーマ、行のまとまりであるfragmentの一覧、索引の一覧を持ち、一度書いたら書き換えません。
(名前は同じですが、Icebergのマニフェストとは別のものです。)
1つのfragmentは1つ以上のデータファイルからなり、各データファイルが1つ以上の列を受け持ちます。
各fragmentには、最初に書いたデータファイル(id、image、text)と、後から追加したembeddingのデータファイルが並びます。
列の追加について、仕様には「新しい列を追加するとき、新しい列のデータは各fragmentに新しいデータファイルを追加する形で加えられ、そのfragmentの既存のすべての行について値が計算される」とあり、既存のデータファイルは書き換えられません9。
削除も、削除した行のオフセットをdeletion fileというファイルに記録し、データファイルは書き換えません。
列の追加も削除も新しい版のマニフェストを書く操作で、この書き込みがコミットにあたり、オブジェクトストレージの「存在しなければ書く」操作(put-if-not-exists)で行います9。
ベクトルの型と、データセットの一部としての索引
Icebergではfloatのlist型として保存していたベクトルを、Lanceでは、Arrowの固定長リスト型(すべての値が同じ次元数を持つ配列)の列として持ちます10。
その列に作るベクトル索引は、データセットの_indices/に置かれ、マニフェストから参照されます。
索引は対象の版とfragmentを記録しているので、ある版を開けば、その版に対応する索引が使えます。
ベクトル索引の土台はIVFで、ベクトルを近いもの同士のグループに分けて探索範囲を絞ります。
クエリに近いグループだけを探索し、他のグループは読みません。
仕様に載っているベクトル索引は、IVF_PQ、IVF_HNSW_SQ、IVF_SQ、IVF_RQ、IVF_FLATです10。
画像や動画を入れるblob列
画像や動画のような大きなバイナリは、blob列として持てます11。
ファイルフォーマット2.2で入ったBlob v2では、値の大きさで置き場が変わり、64KiBまでは列の中に直接、64KiBを超えて4MiBまでは複数の値をまとめた.blobファイルに、4MiBを超える値は専用の.blobファイルに置かれます。
読むときは、値全体を読み込まずに、ファイルのように位置を指定して部分的に読めるtake_blobsがあります。
64KiBを境に値を列の外へ出し、4MiBを境にまとめたファイルと専用のファイルに分けます。
✓ Parquet+Icebergの課題との対応
ここまでの仕組みを、Parquet+Icebergの4つの課題に対応づけます。
| 隙間 | Lance formatでの扱い |
|---|---|
| 1行を取り出すときの読み取り量 | 行グループを持たず、値の大きさで符号化を使い分け、1行の取得を少ない入出力で済ませる |
| 既存の行に列の値を足す書き換え | fragmentに列ごとのデータファイルを追加し、既存のデータファイルは書き換えない |
| ベクトルの型と索引 | 固定長リスト型の列にベクトル索引を作り、索引をデータセットの一部として版管理する |
| 大きなバイナリ | blob列で大きさに応じた置き場に格納し、部分読みのAPIを持つ |
LanceDBとは
Lanceライブラリの上で、検索、テーブルの操作、埋め込みの計算をアプリケーション向けのAPIにまとめたものがLanceDBです12。
提供形態には、主に次の2つがあります12。
- LanceDB OSS — Apache License 2.0の組み込み型ライブラリ。Python、TypeScript、Rustから使える
- LanceDB Enterprise — 検索を分散構成で提供する商用製品
OSSでは、アプリケーションからLanceライブラリまでが1つのプロセスの中で動き、データセットはローカルディスクやS3などに置きます。
検索の種類
次の検索を組み合わせられます12。
- ベクトル検索 — 索引がなければ全件の距離計算、索引を作れば近似最近傍検索
- 全文検索 — BM25によるキーワード検索
- ハイブリッド検索 — ベクトル検索と全文検索の結果を、順位を統合する仕組み(リランカー)でまとめる
-
メタデータのフィルタ —
whereにSQLの述語を書く。既定ではベクトル検索の前に適用される
テーブルの操作と埋め込みの計算
テーブルの操作にはadd、update、deleteと、主キーで更新か挿入かを決めるmerge_insertがあります12。
書き込みのたびに新しい版ができ、checkoutで過去の版を読み、restoreで戻せます。
古い版の整理や新しく入った行の索引への反映は、optimizeで行います。
テーブルの定義に埋め込み関数を結びつけておくと、addのときに埋め込みが自動で計算されます12。
Icebergとの使い分けと、カタログでのつながり
IcebergとLance formatの関係について、Lanceの開発者は2025年4月の記事で、「Icebergを置き換えるのではなく、特定のユースケースに適した機能を提供する」と書いています13。
同じ開発者らの2025年11月の記事では、BI向けの表はIcebergで、AI向けのデータはLanceで持ち、同じデータ基盤の上で両方を使う構成が示されています13。
例えば、BIや分析のSparkやTrinoからはIcebergテーブルを、AIのPyTorchやLanceDBからはLanceテーブルを読み書きする分担です。(あくまで一例です。)
(Icebergの仕様がデータファイルの形式として定めているのはParquet、ORC、Avroなので、IcebergのデータファイルとしてLanceファイルを使えるわけではありません。)
両方を同じ基盤で使うとき、テーブルの一覧と場所の解決を共通にするのがカタログです。
Lance側では、Lance Namespaceという仕様が、これをApache PolarisやApache Iceberg REST Catalogなどのカタログに任せるインターフェースを定めています14。
カタログ側でも、Apache Polarisが2026年1月に、Lanceテーブルを「generic table」として登録し、Icebergテーブルと同じ名前空間で管理できることを公表しています15。
注意点
使い始める前に確認する点を挙げます。
- 新しいファイルフォーマットの版で書いたファイルは、その版に対応していないライブラリでは読めない
- Lanceライブラリはセマンティックバージョニングで、破壊的変更のたびにメジャーバージョンが上がり、2025年12月の1.0.0から2026年9月の12.0.0まで進んでいる7
- LanceDB OSSは単一プロセスの組み込みライブラリで、索引の作成と
optimizeは利用者が呼ぶ - READMEの「ParquetやIcebergより100倍速い」は、1,000文字の文字列1億行から20〜50行をランダムに取り出した2023年の測定で、比較対象のParquetはpyarrowの既定の設定で書かれている16
まとめ
Apache Icebergは、大きな分析用テーブルをファイルの集まりとして管理する仕様で、ファイルの中身はParquetなどに任せてきました。
Lance formatは、この分担の外側にあった読み書きを前提に、ファイルフォーマット、テーブルフォーマット、索引を1つの仕様として定めたものです。
LanceDBはその上で検索とテーブル操作を使えるようにしたもので、カタログを共通にすれば、IcebergとLanceのテーブルを同じデータ基盤の上に並べられます。
参考
一次情報
- Lance Format Specification. https://lance.org/format/
- Pace et al., "Lance: Efficient Random Access in Columnar Storage through Adaptive Structural Encodings" (2025). https://arxiv.org/abs/2504.15247
- LanceDB Docs. https://docs.lancedb.com/
- Apache Iceberg Table Spec. https://iceberg.apache.org/spec/
- Apache Parquet format. https://github.com/apache/parquet-format
- Armbrust et al., "Lakehouse: A New Generation of Open Platforms that Unify Data Warehousing and Advanced Analytics" (CIDR 2021). https://www.cidrdb.org/cidr2021/papers/cidr2021_paper17.pdf
参考にした記事
- Bering Note, "Lance / LanceDBとは何か" (2026-06-28). https://bering.hatenadiary.com/entry/2026/06/28/105546
-
Armbrust et al., "Lakehouse: A New Generation of Open Platforms that Unify Data Warehousing and Advanced Analytics", CIDR 2021. https://www.cidrdb.org/cidr2021/papers/cidr2021_paper17.pdf ↩
-
Mohan et al., "Analyzing and Mitigating Data Stalls in DNN Training", VLDB 2021. "DNN training has a unique data access pattern: it is repetitive across epochs and random within an epoch." https://vldb.org/pvldb/vol14/p771-mohan.pdf ↩
-
Pace et al., "Lance: Efficient Random Access in Columnar Storage through Adaptive Structural Encodings", 2025. https://arxiv.org/abs/2504.15247 ↩ ↩2 ↩3
-
Apache Iceberg Table Spec(バージョン3で追加された型はvariant、geometry、geography、ナノ秒精度のタイムスタンプなどで、ベクトルは含まれない). https://iceberg.apache.org/spec/ / Evolution. https://iceberg.apache.org/docs/latest/evolution/ ↩ ↩2 ↩3 ↩4
-
Apache Parquet format, README. https://github.com/apache/parquet-format/blob/master/README.md / Encodings. https://github.com/apache/parquet-format/blob/master/Encodings.md / parquet.thrift(PageHeader). https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift / PR #585 "Introduces a new LogicalType: FILE". https://github.com/apache/parquet-format/pull/585 ↩ ↩2 ↩3
-
apache/iceberg, Issue #15146 "Efficient column updates in Iceberg". https://github.com/apache/iceberg/issues/15146 / Issue #18297 "Vector Type Support". https://github.com/apache/iceberg/issues/18297 / Issue #17919 "File Type Support". https://github.com/apache/iceberg/issues/17919 ↩ ↩2 ↩3
-
lance-format/lance(README、Releases). https://github.com/lance-format/lance / Lance Format Specification. https://lance.org/format/ ↩ ↩2
-
Lance File Format. https://lance.org/format/file/ / Encodings. https://lance.org/format/file/encoding/ / Versioning. https://lance.org/format/file/versioning/ ↩ ↩2 ↩3
-
Lance Table Format. https://lance.org/format/table/ / Storage Layout. https://lance.org/format/table/layout/ / Transactions. https://lance.org/format/table/transaction/ / Data Evolution. https://lance.org/guide/data_evolution/ ↩ ↩2 ↩3
-
Lance Index Format. https://lance.org/format/index/ / Vector Index. https://lance.org/format/index/vector/ / lance-format/lance, python/python/lance/dataset.py("Vector column ... must be FixedSizeListArray"). https://github.com/lance-format/lance/blob/main/python/python/lance/dataset.py ↩ ↩2
-
Lance, Blob. https://lance.org/guide/blob/ ↩
-
LanceDB Docs. https://docs.lancedb.com/ / FAQ (OSS). https://docs.lancedb.com/faq/faq-oss / Enterprise. https://docs.lancedb.com/enterprise / Vector Index. https://docs.lancedb.com/indexing/vector-index / Full-Text Search. https://docs.lancedb.com/search/full-text-search / Hybrid Search. https://docs.lancedb.com/search/hybrid-search / Filtering. https://docs.lancedb.com/search/filtering / Update. https://docs.lancedb.com/tables/update / Versioning. https://docs.lancedb.com/tables/versioning / Embedding. https://docs.lancedb.com/embedding ↩ ↩2 ↩3 ↩4 ↩5
-
LanceDB Blog, "The Future of Open Source Table Formats: Apache Iceberg and Lance" (Jack Ye, 2025-04-08). https://lancedb.com/blog/the-future-of-open-source-table-formats-iceberg-and-lance/ / "From BI to AI: A Modern Lakehouse Stack with Lance and Iceberg" (Jack Ye, Prashanth Rao, 2025-11-24). https://www.lancedb.com/blog/from-bi-to-ai-lance-and-iceberg ↩ ↩2
-
Lance Namespace. https://lance.org/format/namespace/ / Supported Catalogs. https://lance.org/format/namespace/supported-catalogs/ / Apache Iceberg REST Catalog. https://lance.org/format/namespace/supported-catalogs/iceberg/ ↩
-
Apache Polaris Blog, "Apache Polaris and Lance: Bringing AI-Native Storage to the Open Multimodal Lakehouse" (2026-01-06). https://polaris.apache.org/blog/2026/01/06/apache-polaris-and-lance-bringing-ai-native-storage-to-the-open-multimodal-lakehouse/ ↩
-
LanceDB Blog, "Benchmarking Random Access in Lance" (Chang She, 2023-03-14). https://www.lancedb.com/blog/benchmarking-random-access-in-lance ↩








