2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

ベクトル検索ってなんや?と思い調べてみました。

これを書いているのは以下の人物です。

  • 普段はSQLで業務をしている
  • リレーショナルデータベース(RDB)が思考の土台になっている
  • 「ベクトル検索」「embedding」「RAG」という単語は聞くが、自分の知識と地続きで理解したい中堅エンジニア

ゴールはひとつだけです。

「ベクトル検索は、RDBでいうと結局なんなのか」を、SQLの語彙で説明できるようになる

新しい概念をゼロから覚えるのではなく、「いつものSQL」とどこが同じで・どこが違うのか、という対比で進めます。
元の知識からという形で確認する方が、自分の中で腹落ちするかなと思いましての形式です。


1. まず「いつものSQL検索」を振り返る

普段、こういう検索をします。

-- 完全一致
SELECT * FROM faq WHERE question = '休暇の申請方法';

-- 部分一致(あいまい検索)
SELECT * FROM faq WHERE question LIKE '%休暇%';

-- 全文検索(少し賢い)
SELECT * FROM faq WHERE MATCH(question) AGAINST('休暇 申請');

これらはすべて、文字・単語が一致するかを見ています。
正確で速く、結果の理由も説明しやすい、慣れ親しんだ仕組みです。

ただ、限界もあるよなと思っていて。たとえばユーザーが

「有給を取りたいときの手続き」

と検索しても、休暇の申請方法 という行は 1件もヒットしません
文字が一致しないからです。

でも人間が見れば、この2つはほぼ同じ意味ですよね。

つまり従来のSQL検索は、

  • 「文字が一致しているか」は得意
  • 「意味が近いか」は苦手

という性質を持っている、と整理できそうです。
この「意味が近いものを探したい」を解決するのが、ベクトル検索なのかなと。


2. 「意味」を数字にする = ベクトル(embedding)

調べてみると、ベクトル検索の出発点はとてもシンプルな発想でした。

文章の「意味」を、数値の並び(ベクトル)に変換する

たとえば、こうなります。

「休暇の申請方法」 → [0.21, -0.83, 0.05, ... ]   ← 例えば1536個の数値の並び

この数値の並びを embedding(埋め込み) と呼ぶそうです。ポイントは、この数値がでたらめではないこと。

意味が近い文章ほど、ベクトル(数値の並び)も近くなるように作られている

  • 「休暇の申請方法」
  • 「有給を取りたいときの手続き」

この2つは文字は違いますが、ベクトルとしては近い場所に配置される、というイメージです。

そもそも embedding って何?(正直ここで一番つまずいた)

正直に言うと、自分はここが一番ピンと来ませんでした。
「意味を数字にする」って、何をどうやって数字にしとるんや…? と。

調べて腹落ちしたのは、こういうイメージでした。

embedding = そのものの「特徴」を、いくつもの軸で点数づけしたもの

たとえば、いろいろな単語を「3つの軸」で点数づけしてみるとします(あくまでイメージ用の例です)。

単語 生き物っぽさ 乗り物っぽさ 食べられる度
0.9 0.0 0.1
0.9 0.0 0.1
自動車 0.0 0.9 0.0
りんご 0.2 0.0 0.9

こうすると、各単語が「数字の並び」で表せます。

  • 犬 = [0.9, 0.0, 0.1]
  • 猫 = [0.9, 0.0, 0.1]
  • 自動車 = [0.0, 0.9, 0.0]

犬と猫は数字がほぼ同じ → 意味が近い
犬と自動車は数字が全然違う → 意味が遠い

これがembedding(埋め込み)の正体でした。「意味の特徴」を、座標(数字の並び)として“埋め込む”から、この名前なんですね。

じゃあ、その軸や数字は誰が決めてるの?

ここも気になった所です。さっきは「生き物っぽさ」みたいに人間が軸を決めましたが、本物のembeddingでは事情が違うそうで。

  • 軸は 数百〜数千個 ある
  • しかも各軸が何を表しているのかは、人間には言葉で説明できない(AIが勝手に作った軸)
  • 数字を決めているのは、大量の文章で学習した AIモデル

ざっくり言うと、AIは「似た文脈で使われる言葉どうしは、似た数字になる」ように学習しているとのこと。だから「有給」と「休暇」のように、文字は違うけど近い使われ方をする言葉は、自然と近い数字になる、と。

別のたとえだと、地図の緯度・経度が近いかなと思いました。東京と横浜は座標が近いから「地理的に近い」と判断できますよね。embeddingは、それの“意味バージョン”の座標を、文章ごとに割り振っている――そんなイメージで、自分はようやく納得できました。

RDB的に言うと

難しく考えなくてよさそうです。RDBの頭で言い換えると、

1行 = 1文書 に対して、「意味を表す数値列(ベクトル列)」という新しいカラムが1本増えた

というだけのことかなと。

id content embedding
1 休暇の申請方法 [0.21, -0.83, 0.05, ...]
2 経費精算のやり方 [0.55, 0.10, -0.40, ...]
3 有給休暇の取り方 [0.20, -0.81, 0.07, ...]

id=1id=3 は意味が近いので、ベクトルの数値も近い並びになっている、という具合です。


3. ベクトル検索とは =「近いベクトルを上位N件」

ここが個人的に一番ハッとした所です。

従来のSQL検索 ベクトル検索
判定 一致する / しない(YES/NO) どれくらい近いか(距離)
取り方 条件に合う行を取る 近い順に並べて上位を取る

腹落ちポイントを一言で言うと、

ベクトル検索は、SQLでいうと ORDER BY 距離 LIMIT N である

完全一致の WHERE ではなく、「近い順に並べて上位N件」という発想に変わるわけですね。

-- pgvector(PostgreSQL拡張)での例
SELECT id, content
FROM documents
ORDER BY embedding <=> '[0.20, -0.80, 0.07, ...]'  -- ← 検索したい文章のベクトル
LIMIT 5;

<=> は「コサイン距離」を計算する演算子だそうです。
要は「2つのベクトルがどれだけ似た向きを向いているか」を測っている、と。

距離・類似度の代表例

  • コサイン類似度 / コサイン距離 … ベクトルの「向き」の近さ。文章検索で最もよく使うらしい
  • ユークリッド距離(L2) … 座標上の直線距離

細かい使い分けは後回しにします。
まずは「一致ではなく近さ順 + 上位N件」という発想転換をします。

イメージ(2次元に簡略化)

実際は数百〜数千次元ですが、無理やり2次元に潰すとこうなるイメージです。

        休暇の申請方法 ●
                      ● 有給休暇の取り方     ← この2つは近い(=意味が近い)


   経費精算のやり方 ●                         ← 別の意味なので離れている

「有給を取りたいときの手続き」をベクトル化すると、左上の固まりの近くに落ちます。だから文字が一致しなくても、近い文書を拾えるんですね。


4. 曖昧(あいまい)検索とどう違うのか

RDB畑の人がまず引っかかるのが、ここだと思います。自分も最初そうでした。

「ベクトル検索 = ただの賢い曖昧検索(LIKE / あいまい検索)でしょ?」

調べてみると、実は これは別物 でした。混同するとRAGの設計を間違えそうなので、ここははっきり区別しておきます。

曖昧検索(おさらい)

曖昧検索と呼ばれるものは、だいたい次のいずれかかなと思います。

  • LIKE '%...%' による部分一致
  • ワイルドカード検索
  • 表記ゆれ・打ち間違い(タイプミス)を許容する fuzzy 検索(編集距離 / Levenshtein など)

これらに共通するのは、見ているのが「文字の形・並び」 だという点です。
意味は見ていません。

決定的な違い:「見ているもの」が違う

観点 曖昧検索(LIKE / fuzzy) ベクトル検索
見ているもの 文字の形・並び(表記) 意味
強い場面 表記ゆれ・打ち間違い・部分一致 言い換え・同義語・文脈
「有給を取りたい」→「休暇の申請方法」 ✗ ヒットしない ○ ヒットする
「休假」(誤字)→「休暇」 ○ ヒットしうる △ 拾えるが本来の目的ではない
仕組み 文字列の比較 ベクトルの距離計算

具体例で見ると、イメージしやすいかなと思います。

  • 「休假」(誤字)で「休暇」を探したい → これは曖昧検索(fuzzy)の得意分野。文字が1字違うだけなので、文字ベースで拾える
  • 「有給を取りたいときの手続き」で「休暇の申請方法」を探したい → 文字が一致しないので曖昧検索ではヒットしない。意味が近いのでベクトル検索なら拾える

一言でまとめると、

曖昧検索は 「文字のゆれ」 に強い。ベクトル検索は 「意味のゆれ」 に強い。

向いている仕事が違うだけで、対立する技術ではなさそうです。実務では両方を併用して結果を統合する ハイブリッド検索(キーワード検索+ベクトル検索)もよく使われるみたいです。


5. AI/LLMとどう関係するのか

ここで、ようやくAI/LLMが2つの役割で登場します。

役割①:ベクトルを作るのはAIモデル(embeddingモデル)

「文章 → ベクトル」に変換しているのは、学習済みのAIモデルでした。

  • 「意味が近いと数値も近くなる」という性質は、このモデルが大量の文章を学習した結果として備わっている
  • 例:OpenAIのembeddingモデル、各種オープンソースモデルなど
  • モデルによって出力されるベクトルの次元数が決まっている(例:1536次元)

つまり、ベクトルの「質」はモデル次第ということですね。ここがAIの前処理として効いてくる部分かなと思います。

役割②:LLM(生成AI)と組み合わせる = RAG

ChatGPTのようなLLMは賢いですが、

  • 社内のドキュメント
  • 最新の情報
  • 特定業務のローカルなルール

知りません。そこで、こういう流れを組むそうです。

  1. ユーザーの質問をベクトル化する
  2. ベクトル検索で「関連しそうな社内文書」を上位N件取ってくる
  3. その文書をLLMに渡して「これを参考に答えて」と指示する
  4. LLMが、渡された文書を根拠にして回答を生成する

この仕組みを RAG(Retrieval-Augmented Generation / 検索拡張生成) と呼ぶとのこと。

RDBエンジニアの視点

ここで注目したいのが、RAGの「Retrieval(検索)」の部分です。

RAGの心臓部である「関連文書の検索」は、まさにDBの仕事

ベクトル検索はRAGの土台になっていて、ここがRDBエンジニアの腕の見せ所になりそうです。「AIだから自分には関係ない」ではなく、むしろ得意分野の延長なんだなと、ここで少し安心しました。


6. DBとしてはどうなるのか(テーブルの実体)

RDBの頭で一番気になるのは、たぶんここですよね。自分もそうでした。

「で、結局 テーブル はどうなるの?」

結論から言うと、

テーブルはそのまま存在します。普通のテーブルに、ベクトル型のカラムが1本増えるだけです。

魔法のような別世界ではなく、いつものテーブル設計の延長でした。

6-1. テーブルの実体

PostgreSQL + pgvector(PostgreSQLの拡張)を例にすると、こうなります。

-- 拡張を有効化
CREATE EXTENSION vector;

CREATE TABLE documents (
    id          SERIAL PRIMARY KEY,
    doc_id      INT,            -- 元文書のID
    chunk_no    INT,            -- 文書内で何番目の塊か
    content     TEXT,           -- 本文(チャンク)
    department  TEXT,           -- メタデータ(部署など、普通のカラム)
    created_at  TIMESTAMP,
    embedding   vector(1536)    -- 意味を表すベクトル(floatが1536個入る箱)
);

ポイントは次の3つかなと思います。

  • embedding は専用の型ですが、テーブルの中の1カラムにすぎません
  • departmentcreated_at といった普通のカラムも今まで通り共存できます
  • 主キー・外部キーなど、RDBの作法はそのまま使えます

6-2. 「1行 = 1文書」とは限らない(チャンク)

実務では、長い文書をまるごと1行に入れることは少なく、適切な長さに**分割(チャンク化)**して 1チャンク = 1行 にすることが多いそうです。doc_idchunk_no で元文書に紐づける。これはまさにテーブル設計の話なので、しっくりきました。

元文書(PDF / Wiki ページ)
   ↓ 適当な長さに分割
チャンク1, チャンク2, チャンク3 ...
   ↓ それぞれをベクトル化
各チャンクを1行ずつ documents テーブルへ INSERT

6-3. 検索は普通のSQLと「合成」できる

ここがRDBエンジニア的に一番嬉しかった所です。メタデータの WHERE と、ベクトルの ORDER BY1本のSQLで組み合わせられます

SELECT id, content
FROM documents
WHERE department = '人事部'             -- ① 普通のWHEREで母集団を絞る
  AND created_at >= '2025-01-01'
ORDER BY embedding <=> :query_vector    -- ② その中で「意味が近い順」に並べる
LIMIT 5;

これは「人事部の、今年以降の文書の中から、意味が近いものトップ5」を1本のSQLで表現しています(メタデータフィルタ付きベクトル検索)。WHEREで絞ってからORDER BYで並べる、という構造は、いつものSQLそのものですよね。

6-4. INSERT時・検索時にAIモデルが動く(DBは「数」を比べるだけ)

ここは個人的に一番の勘所だと思いました。

DB自体は「意味を理解」していません。保存された数値ベクトルどうしの距離を、速く計算して並べているだけです。

  • INSERT時:あらかじめembeddingモデルで content をベクトル化し、その数値列を一緒にINSERTする
  • 検索時:検索したい文字列をベクトル化してから、ORDER BY に渡す
  • DBの仕事:渡されたベクトルと、各行のベクトルの距離を計算して近い順に並べる

つまり「賢さ(意味の理解)」はモデル側に閉じていて、DBは今まで通り「速く正確に処理する」役割に徹しているわけです。RDBの世界観のまま理解できる、というのが分かって、だいぶ気が楽になりました。

6-5. インデックスだけは目的が違う

ひとつだけ毛色が違うのがインデックスでした。完全一致で使うB-treeとは目的が異なり、ベクトル検索では 近似最近傍探索(ANN) 用のインデックスを使うそうです。

-- コサイン距離向けのHNSWインデックス
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops);
  • HNSW … グラフ構造を使う。精度・速度のバランスが良い
  • IVFFlat … クラスタに分けて探す。構築が軽い

「全件を正確に比較する」のではなく「だいたい近いものを高速に見つける」ための索引、という点だけ押さえておけばよさそうです。CREATE INDEX の対象である、という枠組み自体は同じでした。

6-6. 専用ベクトルDBとの関係

Pinecone・Weaviate・Milvus・Qdrant といった専用ベクトルDBもあるみたいですが、テーブル・SQL・インデックスという既存スキルがそのまま活きる pgvector から入るのが、RDB畑の自分には一番理解しやすかったです。


7. 何が変わって、何は変わらないのか(まとめ)

完全一致・曖昧検索・ベクトル検索を並べると、立ち位置がはっきりしてきました。

観点 完全一致 曖昧検索(LIKE / fuzzy) ベクトル検索
見るもの 文字が完全に同じか 文字の形が部分一致 / 近いか 意味が近いか
条件の書き方 WHERE = WHERE LIKE ORDER BY 距離 LIMIT N
強み 正確・最速・説明容易 表記ゆれ・打ち間違い 言い換え・同義語・文脈
インデックス B-tree など B-tree / 専用 HNSW / IVFFlat(近似最近傍)
前処理 不要 不要 AIモデルでベクトル化

変わらないこと

  • テーブルに行を入れて、SQLで取り出すという基本構造
  • 普通のカラム(メタデータ)と共存し、WHERE で絞り込めること
  • RDBの設計・運用・インデックスの知識が土台になること

変わること

  • 「一致」から「近さ」へ
  • 検索対象が「文字列」から「意味(ベクトル)」へ
  • 前処理としてAIモデル(ベクトル化)が入ってくること

おわりに

調べてみて思ったのは、ベクトル検索は「SQLの完全一致や曖昧検索をやめろ」という話ではないということでした。**「意味で探したいときの新しい道具が一つ増えた」**くらいの話なのかなと。曖昧検索が「文字のゆれ」に強いように、ベクトル検索は「意味のゆれ」に強い。そして、その新しい道具を支える「検索」と「テーブル設計」は、RDBエンジニアの得意分野そのものでした。

次の一歩としては、ローカルのPostgreSQLに pgvector を入れて、数件のデータで

... ORDER BY embedding <=> :q LIMIT N

を実際に叩いてみたら、一気に腹落ちするはずだと思います。
きっと…

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?