🧲
概念 #データ設計 #ベクトルDB #pgvector #LLM #近似最近傍探索 #DDIA 📚 データ志向アプリケーション設計(DDIA)

ベクトルDBとpgvector

LLM時代の埋め込みベクトル検索の仕組み。コサイン類似度・近似最近傍探索(ANN)・HNSWインデックスの設計、pgvectorとQdrant/Pineconeの使い分けを理解する

定義

ベクトルDB:高次元のベクトル(埋め込み)を格納し、クエリベクトルに最も近いベクトルを効率的に検索するデータベース。LLMが生成する埋め込みをセマンティック検索・レコメンデーション・RAGに活用するための基盤。

なぜ通常のインデックスでは不十分か

通常のBツリーインデックス:
  完全一致・範囲検索に最適
  「id = 123」「price BETWEEN 100 AND 200」

ベクトル検索の問い:
  「このテキスト(1536次元のベクトル)に最も意味が近いドキュメントを返せ」
  → Bツリーは次元が増えると指数的に遅くなる(次元の呪い)
  → 全ベクトルとの距離を計算すると O(N×D) → 大規模DBでは現実的でない

埋め込みベクトル(Embedding)の仕組み

テキスト → LLM(text-embedding-3-small等)→ 数値ベクトル

"猫は動物です" → [0.02, -0.15, 0.87, ..., 0.31]  // 1536次元
"犬は哺乳類です" → [0.03, -0.12, 0.84, ..., 0.28]  // 意味が近いので近いベクトル
"株価が上昇した" → [-0.91, 0.43, -0.21, ..., 0.67]  // 意味が違うので遠いベクトル

類似度:
  コサイン類似度: ベクトルの向きの近さ(-1〜1)
  L2距離(ユークリッド距離): ベクトルの距離
  内積(Dot Product): 正規化済みベクトルならコサイン類似度と等価

近似最近傍探索(ANN)

正確な最近傍を全件スキャンすると遅い。ANNは「近似的に近い」ベクトルを高速に返す。

HNSW(Hierarchical Navigable Small World)

pgvectorとQdrantが採用する最も広く使われるANNアルゴリズム。

アイデア: グラフ構造で「近い点への近道」を事前に構築

多層グラフ:
  Layer 2(粗い): 少数のノード、長距離のエッジ → 大まかな方向へ高速移動
  Layer 1(中間): より多くのノード
  Layer 0(細かい): 全ノード、短距離のエッジ → 精密な最近傍を探す

検索:
  Layer 2から始めてクエリに近いノードに移動
  Layer 0まで降りてきたら局所的な最近傍を返す
  
特性:
  構築: O(N log N)
  検索: O(log N)
  精度とスピードのトレードオフをef_search(探索幅)で調整

pgvectorの使い方

PostgreSQLの拡張機能として動作。既存のPostgreSQLスタックにベクトル検索を追加できる。

-- インストール
CREATE EXTENSION vector;

-- ベクトルカラムを持つテーブル
CREATE TABLE documents (
  id SERIAL PRIMARY KEY,
  content TEXT,
  embedding vector(1536),   -- OpenAI text-embedding-3-small の次元数
  metadata JSONB
);

-- HNSWインデックスの作成
CREATE INDEX ON documents
  USING hnsw (embedding vector_cosine_ops)  -- コサイン類似度
  WITH (m = 16, ef_construction = 64);
-- m: 各ノードのエッジ数(多いほど精度↑、メモリ↑)
-- ef_construction: 構築時の探索幅(多いほど精度↑、構築時間↑)

-- または IVFFlat(メモリ効率が良いが精度がやや低い)
CREATE INDEX ON documents
  USING ivfflat (embedding vector_cosine_ops)
  WITH (lists = 100);  -- クラスター数(sqrt(N)が目安)

類似度検索

-- クエリベクトルに最も近いドキュメントを10件取得
SELECT
  id,
  content,
  1 - (embedding <=> '[0.1, 0.2, ...]'::vector) AS similarity
FROM documents
ORDER BY embedding <=> '[0.1, 0.2, ...]'::vector  -- <=> はコサイン距離
LIMIT 10;

-- 演算子:
-- <=>  コサイン距離(1 - コサイン類似度)
-- <->  L2距離(ユークリッド距離)
-- <#>  負の内積

アプリケーションコードとの統合

import OpenAI from 'openai';
import { Pool } from 'pg';

const openai = new OpenAI();
const pool = new Pool();

// テキストを埋め込みに変換してDBに保存
async function indexDocument(content: string, metadata: object) {
  const response = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: content,
  });
  const embedding = response.data[0].embedding;

  await pool.query(
    'INSERT INTO documents (content, embedding, metadata) VALUES ($1, $2, $3)',
    [content, JSON.stringify(embedding), metadata]
  );
}

// セマンティック検索
async function semanticSearch(query: string, limit = 10) {
  const response = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: query,
  });
  const queryEmbedding = response.data[0].embedding;

  const result = await pool.query(
    `SELECT id, content, metadata,
            1 - (embedding <=> $1) AS similarity
     FROM documents
     ORDER BY embedding <=> $1
     LIMIT $2`,
    [JSON.stringify(queryEmbedding), limit]
  );
  return result.rows;
}

RAG(Retrieval-Augmented Generation)への応用

RAGのフロー:
  1. ユーザーの質問をEmbeddingに変換
  2. ベクトルDBで類似ドキュメントを検索
  3. 検索結果をコンテキストとしてLLMに渡す
  4. LLMが回答を生成

メリット:
  LLMが学習していない最新情報・社内情報を参照できる
  ハルシネーションを減らせる(根拠となる文書を提供)
  
実装例:
  質問: "弊社のQ3売上はどうでしたか?"
  → Embedding → ベクトル検索 → 「Q3決算報告書」を取得
  → "以下の資料に基づいて回答してください: [決算報告書]..."
  → LLMが根拠に基づいた回答を生成

ハイブリッド検索

全文検索(キーワード)とベクトル検索(意味)を組み合わせる。

-- pgvector + PostgreSQLの全文検索を組み合わせる
SELECT
  id,
  content,
  -- 全文検索スコア
  ts_rank(to_tsvector('japanese', content), plainto_tsquery('japanese', $1)) AS fts_score,
  -- ベクトル類似度
  1 - (embedding <=> $2::vector) AS vector_score
FROM documents
WHERE
  to_tsvector('japanese', content) @@ plainto_tsquery('japanese', $1)  -- キーワードフィルタ
ORDER BY
  -- 重み付けで組み合わせ(RRF: Reciprocal Rank Fusion が一般的)
  0.5 * ts_rank(...) + 0.5 * (1 - (embedding <=> $2::vector)) DESC
LIMIT 10;

pgvector vs 専用ベクトルDB

観点pgvectorQdrant / Pinecone / Weaviate
既存スタックPostgreSQLのまま別システムが必要
スケールPostgreSQLの上限(〜1億件が目安)数十億件以上
機能シンプルフィルタリング・スパースベクトル・マルチベクトル
管理コスト低い別途運用が必要
一貫性PostgreSQLのACID最終的一貫性
適した用途中規模RAG・プロトタイプ大規模プロダクション

インデックスのチューニング

-- 検索精度を上げる(遅くなる)
SET hnsw.ef_search = 200;  -- デフォルト40

-- インデックスのサイズ確認
SELECT pg_size_pretty(pg_relation_size('documents_embedding_idx'));

-- 精度の確認(ANNの近似誤差)
-- 正確な最近傍(Exact KNN)とANNの結果を比較
SELECT COUNT(*) FROM (
  SELECT id FROM documents ORDER BY embedding <=> $1 LIMIT 10
) ann
WHERE id IN (
  -- インデックスを使わない正確な検索
  SELECT id FROM documents ORDER BY embedding <-> $1 LIMIT 10
);
-- → 10に近いほど精度が高い

関連概念

出典・参考文献

  • pgvector Documentation — github.com/pgvector/pgvector
  • Yu A. Malkov & D. A. Yashunin, “Efficient and Robust Approximate Nearest Neighbor Search Using HNSW” (2016)
  • Qdrant Documentation — qdrant.tech/documentation
  1. 1. 🗄️データ志向アプリケーション設計:概要
  2. 2. 🧩データモデルとクエリ言語
  3. 3. 💾ストレージエンジンとインデックス
  4. 4. 🔁レプリケーション
  5. 5. 🍕パーティショニング(シャーディング)
  6. 6. 🔒トランザクションとACID
  7. 7. 分散システムの本質的な問題
  8. 8. 🤝一貫性と分散合意
  9. 9. 📦バッチ処理
  10. 10. 🌊ストリーム処理
  11. 11. 📋エンコーディングとスキーマ進化
  12. 12. 🔗Sagaパターンと分散トランザクション
  13. 13. 🏗️データシステムの統合設計
  14. 14. 📸MVCC(多版型同時実行制御)
  15. 15. 📊列指向ストレージとOLAP設計
  16. 16. 🕰️ベクタークロックと因果順序
  17. 17. 🔀CRDT(競合なし複製データ型)
  18. 18. 🔍クエリオプティマイザーと実行計画
  19. 19. キャッシュ戦略とRedis設計
  20. 20. 🔎全文検索と転置インデックス
  21. 21. 🌐NewSQL(分散ACIDデータベース)
  22. 22. 📝WALと論理レプリケーション
  23. 23. 🔌コネクションプーリング
  24. 24. 🚧ゼロダウンタイムマイグレーション
  25. 25. 🆔分散ID生成
  26. 26. 🔄N+1問題とDataLoaderパターン
  27. 27. 📈タイムシリーズDB
  28. 28. 🛡️Row Level Security(行レベルセキュリティ)
  29. 29. 📤Outboxパターン(トランザクショナルアウトボックス)
  30. 30. 💾DBバックアップとPITR
  31. 31. ⚠️データベース設計アンチパターン
  32. 32. 🕸️グラフDB深掘り
  33. 33. 🔋バックプレッシャーとサーキットブレーカー
  34. 34. 🔵コンシステントハッシング
  35. 35. 📋マテリアライズドビュー
  36. 36. 📡DBモニタリングとオブザーバビリティ
  37. 37. 🔐データプライバシーとCrypto-Shredding
  38. 38. ✂️垂直分割(Vertical Partitioning)
  39. 39. 🪟ウィンドウ関数
  40. 40. 🧲ベクトルDBとpgvector
  41. 41. 🔧dbtとデータ変換パイプライン
  42. 42. 📬ジョブキューの設計
  43. 43. 📐正規化理論(1NF〜BCNF)
  44. 44. ☁️クラウドDBサービスの設計思想と選択基準
  45. 45. 🗺️地理空間データとPostGIS
  46. 46. 🔑DBセキュリティと権限管理
  47. 47. 🏔️Lakehouse(Apache Iceberg / Delta Lake)
  48. 48. 📜データコントラクト
  49. 49. 🔭OpenTelemetryとDBトレーシング

出典: pgvector Documentation / Qdrant Documentation