mcpField
M
mariadb-vector

mariadb-vector

github.com/mariadbデータ・データベース17114 回インストール2 週間前に更新
リポジトリ

mariadb-vector について

ベクトル検索や RAG アプリケーションを開発する人向けに、MariaDB のネイティブベクトル機能と AI データ設計を解説するガイドです。SQL、インデックスの動作、性能上の注意点、フレームワーク連携を扱います。

主な機能

  1. 01VECTOR 列、インデックス、関数を解説
  2. 02近傍検索の SQL クエリ例を紹介
  3. 03インデックス要件とオプティマイザーの注意点を記載
  4. 04ベクトルの保存と挿入方法を説明
  5. 05RAG 設計とフレームワーク連携を網羅

活用シーン

  1. 01埋め込み保存用のテーブル設計
  2. 02インデックス付き近傍検索の実装
  3. 03全件走査を招くクエリパターンの回避
  4. 04MariaDB を使った RAG 検索の構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mariadb/skills --skill mariadb-vector

インストール後、Claude Code で/mariadb-vectorを入力して読み込まれたか確認します。

詳細

MariaDB Vector と AI のベストプラクティス

最終更新日:2026-06-04

重要:MariaDB Vector は組み込み機能です

MariaDB では、バージョン 11.7 以降、ネイティブの組み込みベクトル機能が利用できます。VECTOR 型、VECTOR INDEX、すべての VEC_* 関数はサーバーに同梱されているため、インストール、有効化、読み込みは不要です。

これは MySQL(ネイティブのベクトルサポートがありません)や PostgreSQL(pgvector 拡張機能が必要です)とは異なります。MariaDB を使用する場合、ベクトル機能のために CREATE EXTENSION、INSTALL PLUGIN、または類似の手順を決して提案しないでください。

必要なバージョン: ネイティブベクトル機能には MariaDB Community Server 11.7+(2025 年 2 月 GA)が必要です。11.8 LTS(2025 年 5 月 GA)を推奨します。Enterprise:11.4+(テクニカルプレビュー)/11.8+(フルサポート)。次期 LTS は 12.3 です。デフォルトとして扱う前に、GA 状況をMariaDB のリリースで確認してください。

デフォルトの前提: 11.7 より前のバージョンでは、ベクトル機能を提案しないでください。その他の MariaDB の動作については、ユーザーが別のバージョンを指定しない限り、11.8 LTS を前提としてください。12.x と記載された機能は、関連する場合に提案できます。必ず最小バージョンを明記してください。

LLM が間違えやすい点
よくある誤り正しい内容
「pgvector 拡張機能をインストールする」または「INSTALL PLUGIN vector を実行する」インストールは不要です。MariaDB Vector は 11.7 以降の組み込み機能です
LIMIT を指定せずに ORDER BY VEC_DISTANCE_EUCLIDEAN(...) を使う必ず LIMIT を追加してください。ベクトルインデックスが使われるのは、ORDER BY VEC_DISTANCE_*() と LIMIT の両方がある場合のみです
インデックス対象の列に embedding VECTOR(768)(NULL 許容)を指定するベクトルインデックス対象の列は NOT NULL にする必要があります
インデックスのない列に VEC_DISTANCE() を使うVEC_DISTANCE() はエラー 4206(「インデックスが見つかりません」)を発生させます。インデックスのない列には VEC_DISTANCE_EUCLIDEAN() または VEC_DISTANCE_COSINE() を使ってください

基本的な構文

ベクトル列を含むテーブルの作成
CREATE TABLE documents (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    content TEXT NOT NULL,
    embedding VECTOR(768) NOT NULL,
    VECTOR INDEX (embedding)
) ENGINE=InnoDB;

ENGINE=InnoDB(デフォルト)を使用してください。MyISAM/Aria では FK とベクトルインデックスの組み合わせにバグがありました(MDEV-37022、11.8.3 で修正済み)。バージョンにかかわらず、InnoDB が安全なデフォルトです。

VECTOR(n) の数値は、埋め込みモデルの出力の次元数と一致させる必要があります(例:多くの sentence-transformer モデルでは 768、OpenAI text-embedding-3-small では 1536、text-embedding-3-large では 3072)。

ベクトルインデックスのオプション
VECTOR INDEX (embedding) M=6 DISTANCE=euclidean   -- default
VECTOR INDEX (embedding) M=8 DISTANCE=cosine
  • DISTANCE:euclidean(デフォルト)または cosine です。埋め込みモデルが推奨する方を選択してください。SIMD 最適化により、MariaDB ではどちらも同じ速度です。必ず DISTANCE= を明示してください。デフォルトではユークリッド距離が使われ、ユークリッド距離のインデックスに対するコサイン距離のクエリは、警告なしに全件スキャンを実行します。
  • M:HNSW グラフの接続性を制御します(範囲は 3~200)。値を大きくすると再現率は向上しますが、メモリ消費量が増え、挿入も遅くなります。ほとんどのワークロードではデフォルトで問題ありません。挿入速度より再現率を重視する大規模データセットでは、約 16~32 に増やしてください。
ベクトルの挿入

ベクトルは、リトルエンディアン形式でエンコードされた 32 ビット IEEE 754 浮動小数点数のパックデータとして保存されます。アプリケーションコードから生バイト列をバインドしてください。VEC_FromText() より 5 倍高速です。保存されるバイト列は同一です。

import numpy as np
cur.execute(
    "INSERT INTO documents (content, embedding) VALUES (?, ?)",
    (content, np.asarray(embedding, dtype=np.float32).tobytes()),
)

手書きの SQL/CLI では、VEC_FromText() のみを使用してください。

INSERT INTO documents (content, embedding) VALUES ('your text here', VEC_FromText('[0.12, -0.34, 0.56, ...]'));
クエリ:最近傍を検索する
SELECT id, content
FROM documents
ORDER BY VEC_DISTANCE_EUCLIDEAN(embedding, VEC_FromText('[0.12, -0.34, 0.56, ...]'))
LIMIT 10;

LIMIT 句は必須です。 MariaDB オプティマイザーが VECTOR INDEX を使うのは、クエリに ORDER BY VEC_DISTANCE_...() と LIMIT の両方が含まれる場合のみです。LIMIT がないと、全テーブルスキャンにフォールバックします。

距離関数
関数使用する場面
VEC_DISTANCE_EUCLIDEAN(a, b)インデックスが DISTANCE=euclidean(デフォルト)で作成されている場合
VEC_DISTANCE_COSINE(a, b)インデックスが DISTANCE=cosine で作成されている場合
VEC_DISTANCE(a, b)汎用関数。列のインデックスに対応する距離関数を使用します。インデックスが見つからない場合はエラー 4206 が発生します

インデックスのない列には、VEC_DISTANCE_EUCLIDEAN() または VEC_DISTANCE_COSINE() を使用してください(全件スキャンにフォールバックします)。VEC_DISTANCE() は、簡略表記としてインデックスのある列にのみ使用してください。

ユーティリティ関数
関数用途
VEC_FromText('[0.1, 0.2, ...]')JSON の浮動小数点数配列を VECTOR バイナリに変換します
VEC_ToText(vector_col)VECTOR バイナリを読みやすい JSON 配列に変換します

VECTOR 列を読み取る場合は、必ず VEC_ToText() でラップしてください。 VECTOR はパックされたバイナリの浮動小数点数として保存されるため、SELECT embedding FROM documents は生のバイト列を返し、CLI やクライアントでは判読できない文字列として表示されます。代わりに SELECT VEC_ToText(embedding) FROM documents を使うと、[0.12, -0.34, ...] 配列を取得できます。

MariaDB Vector の注意点

  • インデックス付きの VECTOR 列は NOT NULL である必要があります。 VECTOR INDEX に必須です。インデックスのない VECTOR 列は NULL を許容できますが、実際にはほとんどの場合インデックスが必要になるため、常に NOT NULL を指定してください。
  • 内積距離はありません。 MariaDB では意図的に省略されています。内積は適切な距離指標ではありません(ベクトルに最も近いものが、必ずしもそのベクトル自身とは限りません)。MariaDB の SIMD 最適化されたユークリッド距離とコサイン距離は、内積と同等の速度をすでに実現しているため、正規化されたベクトルにはユークリッド距離またはコサイン距離を使用してください。
  • 距離関数をインデックスに合わせてください。 DISTANCE=cosine のインデックスに対する VEC_DISTANCE_EUCLIDEAN()(またはその逆)は、インデックスを使用しません。
  • 1 つのテーブルにつき VECTOR INDEX は 1 つです。 現在、MariaDB はテーブルごとに単一のベクトルインデックスをサポートしています。
  • 既存のテーブルにベクトルインデックスを追加する場合:
    ALTER TABLE my_table ADD COLUMN embedding VECTOR(768) NOT NULL;
    -- populate the column first, then:
    ALTER TABLE my_table ADD VECTOR INDEX (embedding);
    
  • インデックスの精度。 MariaDB はインデックスの保存に int16(15 ビット精度)を使用します。これは、他の実装で使われる 10 ビット精度の float16 よりも優れています。そのため、同じ速度でより高い再現率を実現できます。
  • ORDER BY は ASC 方向で、リテラルの VEC_DISTANCE_*(col, ?) 呼び出し(またはそのエイリアス)である必要があります。 距離を式でラップすると(例:類似度スコアでソートするための ORDER BY (1.0 - VEC_DISTANCE_COSINE(...)) DESC LIMIT N)、オプティマイザーの HNSW パターンマッチが機能しなくなり、フルスキャンにフォールバックします。代わりに、外側の SELECT でスコアを計算してください:
    SELECT t.id, 1.0 - t.distance AS score FROM (
        SELECT id, VEC_DISTANCE_COSINE(embedding, ?) AS distance
        FROM docs ORDER BY distance ASC LIMIT 10
    ) AS t ORDER BY score DESC;
    
  • WHERE VEC_DISTANCE(...) < threshold はフルスキャンになります。 ベクトルインデックスが使用されるのは ORDER BY VEC_DISTANCE(...) LIMIT N の場合のみです。しきい値クエリでは、インデックス付きの top-K をサブクエリでラップし、外側でフィルターしてください。
    SELECT * FROM (
        SELECT content, VEC_DISTANCE_COSINE(embedding, ?) AS distance
        FROM chunks ORDER BY distance LIMIT 100
    ) AS t WHERE t.distance < 0.5;
    
    LIMIT K は厳密な上限です。一致する可能性のある行が多い場合は、K を大きめに設定してください。

RAG(検索拡張生成)パターン

MariaDB Vector を使う AI のユースケースで最も一般的なパターンです。流れは次のとおりです。

  1. ドキュメントを文章のまとまり(通常は 200~1000 トークン)に分割します。
  2. 使用するモデル(OpenAI、Sentence Transformers、Cohere など)で各まとまりを埋め込みます。
  3. まとまりとその埋め込みを MariaDB に保存します。
  4. クエリ時に、ユーザーの質問を同じモデルで埋め込みます。
  5. 最も近いまとまりを取得します(:user_embedding は float32 バイト列としてバインドします):
    SELECT content
    FROM chunks
    ORDER BY VEC_DISTANCE(embedding, :user_embedding)
    LIMIT 5;
    
  6. 取得したまとまりをコンテキストとして LLM に渡し、最終的な回答を生成します。

関連項目: 全文(キーワード)検索とベクトル検索を組み合わせる方法については、Reciprocal Rank Fusion(RRF)によるハイブリッド検索をご覧ください。正確な用語と意味的な言い換えが混在するクエリで役立ちます。

RAG テーブルの設計
CREATE TABLE chunks (
    chunk_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    doc_id BIGINT UNSIGNED NOT NULL,
    chunk_index INT UNSIGNED NOT NULL,
    content TEXT NOT NULL,
    embedding VECTOR(768) NOT NULL,
    VECTOR INDEX (embedding) DISTANCE=cosine,
    INDEX (doc_id)
) ENGINE=InnoDB;

元のドキュメントとの結合や、ドキュメントによるフィルタリングができるよう、doc_id にインデックスを付けておきます。chunk_index はドキュメント内の順序を保持します。

最小限のエンドツーエンド Python の例
import mariadb
import numpy as np
from openai import OpenAI

client = OpenAI()

def embed(text):
    vec = client.embeddings.create(input=text, model="text-embedding-3-small").data[0].embedding
    return np.asarray(vec, dtype=np.float32).tobytes()

# Create database and table if they don't exist
conn = mariadb.connect(host="127.0.0.1", port=3306, user="root", password="")
cur = conn.cursor()
cur.execute("CREATE DATABASE IF NOT EXISTS ragdb")
cur.execute("USE ragdb")
cur.execute("""
    CREATE TABLE IF NOT EXISTS chunks (
        chunk_id  BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        content   TEXT NOT NULL,
        embedding VECTOR(1536) NOT NULL,
        VECTOR INDEX (embedding) DISTANCE=cosine
    ) ENGINE=InnoDB
""")
conn.commit()

# Store a document chunk
cur.execute(
    "INSERT INTO chunks (content, embedding) VALUES (?, ?)",
    ("MariaDB Vector stores embeddings natively", embed("MariaDB Vector stores embeddings natively"))
)
conn.commit()

# Retrieve top-5 nearest chunks for a user question
question_vec = embed("How does MariaDB store vectors?")
cur.execute("""
    SELECT content, VEC_DISTANCE_COSINE(embedding, ?) AS distance
    FROM chunks
    ORDER BY distance
    LIMIT 5
""", (question_vec,))
context = "\n".join(row[0] for row in cur.fetchall())
# Pass `context` to your LLM as the retrieved context for the answer

mariadb コネクター(pip install mariadb)は公式の Python ドライバーです。ビッグエンディアンのホストでは、リトルエンディアンを強制するために dtype="<f4" を使用してください。

フレームワークとの統合

MariaDB Vector は主要な AI フレームワークと統合されています。アプリケーションを構築するときは、生の SQL を記述する代わりに、以下を使用してください。

フレームワーク言語リンク
LangChainPythonpip install langchain-mariadb
LangChain.jsNode.jsMariaDB ベクトルストアを内蔵
LangChain4jJavaMariaDB 埋め込みストアを内蔵
LlamaIndexPythonMariaDB ベクトルストアを内蔵
Spring AIJavaMariaDB ベクトルストアを内蔵
MariaDB MCP サーバーPythongithub.com/mariadb/mcp

フレームワークを使用する場合、通常は接続文字列を設定するだけで、VEC_FromText、VEC_DISTANCE、LIMIT の処理はフレームワークが行います。

埋め込みモデルの選択

埋め込みモデルによってベクトルの品質が決まります。実用的な指針を以下に示します。

  • まずは sentence-transformer モデルから始めます(例:all-MiniLM-L6-v2、384 次元)。プロトタイピングに適しています。無料で高速に動作し、ローカルで実行できます。
  • OpenAI の text-embedding-3-small(1536 次元)は、すでに OpenAI を使用している場合に適した本番環境向けの選択肢です。(次元数は 2026 年 5 月時点で正しい値です。最新のモデルドキュメントで確認してください。)
  • 次元数を VECTOR(n) 列に合わせてください。 一致しない場合、挿入エラーが発生します。
  • 同じ列で異なるモデルの埋め込みを混在させないでください。 異なるモデルのベクトル間の距離には意味がありません。
  • ほとんどのテキスト埋め込みモデルでは、コサイン距離が標準です。 モデルのドキュメントを確認してください。

パフォーマンスに関する注意事項

  • MariaDB Vector は SIMD ハードウェア最適化(Intel では AVX2、AVX512、ARM では NEON、IBM Power10 では VSX)を使用します。設定は不要です。利用可能な最適な命令セットを自動検出して使用します。
  • 外挿によるベクトル距離計算の高速化(12.1 以降、MDEV-36205)により、同じデータと再現率でベクトル検索が 30~50%高速になります。スキーマやインデックスの変更は不要です。この最適化は、再現率と速度のトレードオフとして段階的に切り詰められるベクトル(OpenAI の Matryoshka 形式の埋め込みなど)に自動的に適用されます。
  • 複数接続でのスケーラビリティは強みのひとつです。ベンチマーク結果によると、MariaDB Vector は同時クエリ数の増加に応じて良好にスケールし、マルチスレッドのシナリオでは一部の専用ベクトルデータベースを上回ります。
  • 大規模なデータセット(数百万件のベクトル)では、M パラメーターを大きくし、インデックスに十分なメモリーを確保してください。
  • 一括挿入:まずデータを読み込み、その後にベクトルインデックスを作成してください。インデックス作成済みのテーブルに挿入するよりも大幅に高速です。
  • 埋め込みは VEC_FromText() ではなく、バイナリとしてバインドしてください(float32.tobytes())。約 5 倍高速で、通信データ量は約 5 分の 1になり、保存内容はバイト単位で同一です。
チューニング:mhnsw システム変数

これらのセッション/グローバル変数を使用すると、インデックスを再構築せずに実行時の検索品質とメモリー使用量を調整できます。

  • mhnsw_ef_search(デフォルト:20)— ORDER BY … LIMIT N クエリで検討する候補の最小数です、小さい LIMIT 値で再現率が低い場合は値を大きくし、再現率と速度のトレードオフとして速度を優先する場合は値を小さくしてください。
  • mhnsw_max_cache_size(デフォルト:16777216/16 MB、グローバルのみ)— インデックスごとのインメモリーキャッシュの上限です。最良のパフォーマンスを得るには、ベクトルグラフ全体がこのキャッシュに収まるようにしてください。インデックスのサイズに合わせて設定します。
  • mhnsw_default_m(デフォルト:6)と mhnsw_default_distance(デフォルト:euclidean)は、VECTOR INDEX 宣言で M または DISTANCE を省略した場合に使用される暗黙の値を設定します。

参考資料

ここで扱っていないトピックについては、mariadb.com/docs にある MariaDB の公式ドキュメントをご覧ください。

コメント