
2026/08/26 1:52
Show HN: LatticeDB – グラフデータベース向けの SQLite のようなもの
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
LatticeDB は、単一のポータブルファイルに保存される高性能な埋め込み属性グラフデータベースであり、一台のマシン上でのローカルファーストアプリケーションのためにユニークに設計されています。ネイティブ HNSW ベクター検索と BM25 全文インデックスを構成要素なしで一つのエンジンに統合しています。Zig で記述され、外部依存関係を持たず、Python、TypeScript/Go、CLI、C の複数言語へのバインドを提供するとともに、永続的なイベントロギングと組み込みのグラフチェンジフィードを活用して ACID トランザクションを確保します。
単一ライター環境向けに設計されており、ナノ秒級のノードルックアップ(0.13 μs)とベクター検索での完全なリコール(100 万ベクターで 0.83 ms)を実現し、SQLite のような従来のディスクベースシステムを最大 23 倍も上回る性能を発揮し、Weaviate などのサーバーサイド代替品とも競合しています。また、MERGE/UNWIND、ハッシュ埋め込み、Levenshtein 距離による模糊検索、効率的な隣接キャッシュを使用したグラフ走査といった高度な操作もサポートします。
軽量でありリッチなデータ特徴をローカルに組み込むのに最適ですが、LatticeDB は複数ライターのシナリオ、単一マシンを超えた分散スケーリング、OPTIONAL MATCH などの完全な Cypher 機能が必要なアプリケーションには適していません。標準的な SQL テーブル限定ワークフローや厳格な複数ユーザの同時性を必要とするチームは、他のツールを検討すべきです。
本文
LatticeDB:ネイティブベクトルと全文検索を備えた埋め込み型プロパティグラフデータベース
LatticeDB は、関係性データ、セマンティックデータ、テキストデータを扱うための単一ファイル型のローカルデータベースです。一つのエンジンとクエリレイヤーだけで、関係性の探索、ベクトル類似度検索、BM25 による全文検索を同一のデータセットで実行可能です。
特徴とコンセプト
LatticeDB はゼロ構成で動作する埋め込み型の単一ライターモデルを採用しており、一台のマシン上で関係性が重視されるワークロード向けに設計されています。Graph RAG、エージェントメモリ、ローカルな知識ツールなどは、このデータベースを基盤としたワークロードの例です。
- 一つのファイル: データベース全体がポート可能な単一ファイルで、サーバーや設定は不要です。
- 一つのクエリレイヤー: グラフ探索、HNSW ベクトル類似度検索、BM25 全文検索を同じクエリ言語の中で実行可能です。
- 一つのイベントログ: デュアブルな命名されたストリームと組み込みのグラフチェンジフィードは、書き込みと同じトランザクション/WAL パスを共有します。
- ローカルフースト: 一台のマシン上で一つのオーナープロセス向けに設計され、WAL を介した耐久性を備えています。
- 高速:
- ノード検索: 0.13 μs
- 100 万ベクトルでの 100% Recall ベクトル検索: 0.83 ms
インストール方法
CLI
curl -fsSL https://raw.githubusercontent.com/jeffhajewski/latticedb/main/dist/install.sh | bash
Python
公開された wheels は
liblattice をバンドルしています。ソースからのインストールでは、以下の環境変数を指定してネイティブライブラリをバンドルできます:
LATTICE_BUNDLE_LIB_DIR=/path/to/lib pip install ...
TypeScript / Node.js
npm install @hajewski/latticedb
パッケージには
liblattice がバンドルされており、ソースからのビルドでは以下でネイティブライブラリをステージできます:
LATTICE_BUNDLE_LIB_DIR=/path/to/lib npm run bundle:native
Go
最新の cgo ワークフローについては bindings/go/README.md を参照してください。開発では
-tags repolocal フラグを zig-out/lib に使用可能です。
入門ガイド
- Getting Started: CLI, Python, TypeScript, Go の最短学習パス
- CLI Quickstart: コピー&ペースト可能な最小限の例
- Examples Overview: グラフ/ベクトル/テキスト検索のデモ
ワークフローのコード例
Cypher による例
類似したチャンクを検出し、ドキュメント経由で著者へ探索するクエリ:
MATCH (chunk:Chunk)-[:PART_OF]->(doc:Document)-[:AUTHORED_BY]->(author:Person) WHERE chunk.embedding <=> $query_vector < 0.3 AND doc.content @@ "neural networks" RETURN doc.title, chunk.text, author.name ORDER BY chunk.embedding <=> $query_vector LIMIT 10
Python による完全な例
from latticedb import Database from latticedb.embedding import hash_embed with Database("knowledge.db", create=True, enable_vectors=True, vector_dimensions=128) as db: # --- グラフの構築 --- with db.write() as txn: alice = txn.create_node(labels=["Person"], properties={"name": "Alice", "field": "ML"}) bob = txn.create_node(labels=["Person"], properties={"name": "Bob", "field": "Systems"}) txn.create_edge(alice.id, bob.id, "COLLABORATES_WITH") for title, text, author in [ ("Attention Is All You Need", "The transformer architecture...", alice), ("Scaling Laws for LLMs", "We find that model performance scales...", alice), ("Log-Structured Merge Trees", "LSM trees optimize write-heavy workloads...", bob), ]: doc = txn.create_node(labels=["Document"], properties={"title": title}) chunk = txn.create_node(labels=["Chunk"], properties={"text": text}) # 埋め込みの保存とテキストのインデックス化 txn.set_vector(chunk.id, "embedding", hash_embed(text, dimensions=128)) txn.fts_index(chunk.id, text) txn.create_edge(chunk.id, doc.id, "PART_OF") txn.create_edge(doc.id, author.id, "AUTHORED_BY") # --- クエリ: ベクトル検索 + テキスト一致 + グラフ探索 --- results = db.query(""" MATCH (chunk:Chunk)-[:PART_OF]->(doc:Document)-[:AUTHORED_BY]->(author:Person) WHERE chunk.embedding <=> $query < 0.5 RETURN doc.title, chunk.text, author.name ORDER BY chunk.embedding <=> $query LIMIT 5 """, parameters={"query": hash_embed("transformer attention mechanism", dimensions=128)}) for row in results: print(f"{row['doc.title']} by {row['author.name']}")
TypeScript による例
import { Database } from "@hajewski/latticedb"; import { hashEmbed } from "@hajewski/latticedb/embedding"; const db = new Database("knowledge.db", { create: true, enableVectors: true, vectorDimensions: 128, }); await db.open(); await db.write(async (txn) => { const alice = await txn.createNode({ labels: ["Person"], properties: { name: "Alice" } }); const doc = await txn.createNode({ labels: ["Document"] }); const chunk = await txn.createNode({ labels: ["Chunk"] }); await txn.setVector(chunk.id, "embedding", hashEmbed("transformer self-attention", 128)); await txn.ftsIndex(chunk.id, "The transformer architecture uses self-attention..."); await txn.createEdge(chunk.id, doc.id, "PART_OF"); await txn.createEdge(doc.id, alice.id, "AUTHORED_BY"); }); const results = await db.query( `MATCH (chunk:Chunk)-[:PART_OF]->(doc:Document)-[:AUTHORED_BY]->(author:Person) WHERE chunk.embedding <=> $query < 0.5 RETURN doc.title, chunk.text, author.name ORDER BY chunk.embedding <=> $query`, { query: hashEmbed("attention mechanism", 128) } ); for (const row of results.rows) { console.log(`${row["doc.title"]} by ${row["author.name"]}`); }
Go による例
db, err := latticedb.Open("knowledge.db", latticedb.OpenOptions{ Create: true, EnableVectors: true, VectorDimensions: 128, }) if err != nil { log.Fatal(err) } defer db.Close() err = db.Update(func(tx *latticedb.Tx) error { node, _ := tx.CreateNode(latticedb.CreateNodeOptions{ Labels: []string{"Chunk"}, Properties: map[string]latticedb.Value{"text": "The transformer..."}, }) if err := tx.SetVector(node.ID, "embedding", []float32{1, 0, 0, 0}); err != nil { return err } return tx.FTSIndex(node.ID, "The transformer...") }) if err != nil { log.Fatal(err) }
パフォーマンス評価
Apple M1(シングルスレッド、自動調整されたバッファプール)でのベンチマーク結果です。再現するには
zig build benchmark を実行してください。
コア操作のレイテンシ
| 操作 | レイテンシ | スループット | ターゲット | ステータス |
|---|---|---|---|---|
| ノード検索 | 0.13 μs | 790 万 ops/sec | < 1 μs | PASS |
| ノード作成 | 0.65 μs | 150 万 ops/sec | — | — |
| エッジ探索 | 9 μs | 11.1 万 ops/sec | — | — |
| 全文検索 (100 ドキュメント) | 19 μs | 5.3 万 ops/sec | — | — |
| 10-NN ベクトル検索 (100 万ベクトル) | 0.83 ms | 1.2 千 ops/sec | < 10 ms @ 1M | PASS |
スケールにおけるベクトル検索 (HNSW)
設定:128 次元、M=16, ef_construction=200, ef_search=64, k=10。
zig build vector-benchmark で再現可能。
| スケール | メアンレイテンシ | P99 レイテンシ | Recall@10 | メモリ |
|---|---|---|---|---|
| 1,000 | 65 μs | 70 μs | 100% | 1 MB |
| 10,000 | 174 μs | 695 μs | 99% | 10 MB |
| 100,000 | 438 μs | 1.2 ms | 99% | 101 MB |
| 1,000,000 | 832 μs | 1.8 ms | 100% | 1,040 MB |
検索レイテンシは 99–100% の Recall@10 を達成しながら線形未満(O(log N))のスケールを行います。多様なグラフ接続性を確保し、メモリ使用量を削減するための最適化も含まれています。
ef_search の感度 (100 万ベクトル)
| ef_search | メアンレイテンシ | Recall@10 |
|---|---|---|
| 16 | 506 μs | 57% |
| 32 | 1.9 ms | 79% |
| 64 | 990 μs | 100% |
| 128 | 3.2 ms | 100% |
| 256 | 11.6 ms | 100% |
競争分析:ポインタルックアップ
LatticeDB の B+Tree はサブマイクロ秒でのキャッシュされたルックアップを実現し、RocksDB インメモリーと同等の性能を持ち、ディスク上の SQLite よりも 23 倍高速です。
| システム | レイテンシ | タイプ |
|---|---|---|
| LatticeDB | 0.13 μs | 埋め込み |
| RocksDB (インメモリー) | 0.14 μs | 埋め込み |
| SQLite (インメモリー) | ~0.2 μs | 埋め込み |
| SQLite (WAL, ディスク) | 3 μs (p90) | 埋め込み |
| Neo4j | 28 ms (p99) | サーバー |
競争分析:ベクトル検索 (10-NN, 100 万ベクトル)
LatticeDB は 100 万ベクトルで Recall@10 100%、平均 0.83 ms を達成しており、シングルスレッド FAISS HNSW よりも高速です。サーバー系システム(Weaviate, Qdrant)とも競争力があります。
| システム | レイテンシ | タイプ |
|---|---|---|
| LatticeDB | メアン 0.83 ms, Recall 100% | 埋め込み |
| FAISS HNSW (シングルスレッド) | 0.5–3 ms | ライブラリ |
| Weaviate | メアン 1.4 ms, P99 3.1 ms | サーバー |
| Qdrant | ~1–2 ms | サーバー |
| pgvector HNSW | ~5 ms @ 99% recall | 拡張機能 |
競争分析:グラフ探索 (2 ホップ、10 万ノード)
LatticeDB は 39 μs で完了し、Neo4j (10ms)、Kuzu (19ms) よりも高速です。
| システム | レイテンシ | タイプ |
|---|---|---|
| LatticeDB | 39 μs | 埋め込み |
| SQLite (再帰的 CTE) | 548 μs | 埋め込み |
| Kuzu | 19 ms | 埋め込み |
| Neo4j | 10 ms | サーバー |
ディープスリミテッド探索の速度差 (LatticeDB vs SQLite)
深い深さにおいて、SQLite の CTE オーバーヘッドが顕著に増加します。
| 深さ | LatticeDB | SQLite | スピードアップ |
|---|---|---|---|
| 10 | 311 μs | 121 ms | 390 倍 |
| 15 | 380 μs | 271 ms | 713 倍 |
| 25 | 318 μs | 587 ms | 1,848 倍 |
| 50 | 500 μs | 1.4 s | 2,819 倍 |
競争分析:全文検索 (BM25)
LatticeDB の逆数インデックスは、SQLite FTS5 よりも約 300 倍高速です。
| システム | 検索レイテンシ | タイプ |
|---|---|---|
| LatticeDB | 19 μs | 埋め込み |
| SQLite FTS5 | < 6 ms | 埋め込み |
| Elasticsearch | 1–10 ms | サーバー |
機能一覧
- グラフ: ラベルと任意のプロパティ、永続的な明示的等値インデックス、マルチホップ探索、ACID トランザクション。
- ベクトル検索: HNSW 近似近傍検索(設定可能な M, ef)、バッチベクトルノード挿入。
- 全文検索: BM25 ランク付け逆数インデックス、Levenshtein 距離によるファジー検索。
- Cypher クエリ言語: MATCH, WHERE, RETURN, CREATE, DELETE 等の全機能をサポート。
(ベクトル距離),<=>
(全文検索) 演算子対応。@@
操作特性
- 単一ファイルストレージ: クラッシュ回復用のログ付き書き込み前ログを備え、ゼロ構成で動作。
- 永続的なイベントログ: 明示的なコンシューマーオフセットとグラフチェンジフィードに対応。
- メンテナンス:
を使用してオンラインフリーリストを再利用し、物理的テール廃棄を行う。lattice compact - 互換性: Clean C API および Python, TypeScript, Go バインディングを提供。
主な使用例
- 相互接続されたローカルデータ: ノート、ドキュメント、引用グラフの構築。
- グラフプラスリトリバル: 関係性探索、セマンティック検索、辞書的検索を同一データセットで実行。
- ローカル知識ツール: サーバーなしの埋め込み型アプリやエージェントメモリ/RAG パイプラインの基盤。
- 軽量な代替手段: ローカル開発用として Neo4j や Weaviate の代わりに使用可能。
別のツールを選ぶべきケース
LatticeDB は高速ですが、速度だけが重要でない場合や以下の要件がある場合は他を検討してください:
- マルチライター環境: LatticeDB は単一ライターモデルです。多数のクライアントを接続する場合は Neo4j や PostgreSQL などのクライアントサーバー型を選択してください。
- 主に表形式データ: レコード間の関係性が主目的でない場合(売上記録など)、SQLite や PostgreSQL のリレーショナルデータベースの方がシンプルで高速です。
- 大規模スケーリング: シャarding や分散クエリが必要な場合は、Neo4j クラスタやマネージドサービスを検討してください。
- 完全な Cypher 機能:
やコールプロシージャなどの一部の機能が未実装の場合、Neo4j が適しています。OPTIONAL MATCH - エコシステム: 管理ダッシュボードや豊富なライブラリを必要とする場合、既存の成熟したツールの方が有利です。
ソースからビルド
Zig で書かれており依存関係はありません。
git clone https://github.com/jeffhajewski/latticedb.git cd latticedb zig build # すべてのものをビルド zig build test # テストを実行 zig build -Doptimize=ReleaseFast # 最適化ビルド
ドキュメント
- Getting Started
- Durable Streams and Graph Changefeeds
- Architecture Overview
- Client API Migration Notes
- API Reference (Python, TypeScript, Go)
ライセンス: MIT