📖

TiDBでベクトル検索

に公開

はじめに

ChatGPTのような生成AIの登場により、**ベクトル検索(Vector Search)**という技術が注目されています。これは、文章、画像などを数値のベクトル(数字の配列)に変換し、その「意味の近さ」や「特徴の類似度」に基づいてデータを検索する技術です。
きっかけは、TiDBユーザグループ ミートアップ #5に参加し、そこでTiDBのベクトル検索の紹介があり、どんなものかと試してみたことです。

これまでベクトル検索には専門のデータベースが必要でしたが、TiDBでもついにネイティブサポートが追加されました。この記事では、TiDBを使ってベクトル検索を行う基本的な手順を、実際に筆者が遭遇した多くのエラーとその最終的な解決策までを含めて、チュートリアルとして解説します。

前提条件

TiDBでインデックス作成の記事で使用したTiDBのプロジェクトを使用します。

最終的なゴール

  • VECTOR型のカラムを持つテーブルを作成する。
  • ベクトルデータを挿入する。
  • VEC_COSINE_DISTANCE関数を使い、類似ベクトルを検索する。

環境準備:【最重要】バージョンと起動設定

TiDBのベクトル検索は比較的新しい機能のため、ローカル環境(tiup playground)で試すには特定のバージョンと起動設定が必須です。ここが最初にして最大のハマりどころです。

  • 必要なTiDBバージョン: v8.4.0以降
  • 必要な起動オプション: サーバーの実験的機能を有効にする設定ファイル

ステップ1: TiDB用の設定ファイルを作成する

まず、viなどのエディタで以下の内容のファイルを作成します。このファイルは、「ベクトル検索機能を有効にする」という設定を意味します。

./src/infra/db/tidb/tidb-config.toml
[experimental]
enable-vector-search = true

ステップ2: 正しいバージョンと設定でTiDBを起動する

作成したコンテナにアクセスしtiup playgroundコマンドに、バージョンと先ほど作成した設定ファイルを指定して起動します。

# 既存のplaygroundがあれば一度クリーンアップ
tiup playground clean
# v8.4.0 と設定ファイルを指定して起動
tiup playground v8.4.0 --db.config ./tidb-config.toml

チュートリアル:類似文章を検索する

1. テーブルの作成

ベクトルデータを保存するためのテーブルを作成します。新しいデータ型VECTORがポイントです。VECTOR<FLOAT>(次元数)のように、要素の型と次元数を指定します。

./src/infra/db/tidb/data/vector_db.sql
CREATE DATABASE IF NOT EXISTS vector_db;
USE vector_db;
CREATE TABLE vector_table (
    id INT,
    title VARCHAR(255),
    embedding VECTOR<FLOAT>(4),
    PRIMARY KEY (id)
);

(実際のAIモデルでは、次元数は1536次元など、より大きくなります)

2. ベクトルデータの挿入

事前にAIモデルで文章をベクトル化したという想定で、データを挿入します。ベクトルデータは角括弧[]で囲んだ文字列として渡します。

./src/infra/db/tidb/data/vector_db.sql
INSERT INTO vector_table (id, title, embedding) VALUES
(1, '今日の天気は晴れです', '[0.1, 0.3, 0.5, 0.7]'),
(2, '昨日の天気は雨でした', '[0.2, 0.4, 0.6, 0.8]'),
(3, '美味しいレストランを紹介します', '[0.8, 0.6, 0.4, 0.2]'),
(4, 'おすすめのカフェ情報', '[0.7, 0.5, 0.3, 0.1]');

3. ベクトル検索の実行

いよいよ検索です。「人気の飲食店」という文章をベクトル化したものが[0.75, 0.55, 0.35, 0.15]だとします。このベクトルとデータベース内の各ベクトルのコサイン類似度を計算し、最も近いもの(距離が小さいもの)を探します。

SELECT
    id,
    title,
    -- VEC_COSINE_DISTANCE関数で検索ベクトルとの距離を計算
    VEC_COSINE_DISTANCE(embedding, '[0.75, 0.55, 0.35, 0.15]') AS distance
FROM
    vector_table
-- ORDER BY句で距離が近い順に並び替え
ORDER BY
    distance ASC
LIMIT 3;

実行結果

「人気の飲食店」というクエリに対し、意味的に近い「美味しいレストラン」や「おすすめのカフェ」が上位にランク付けされて返ってきます。

id title distance
3 美味しいレストランを紹介します 0.0008254166479818581
4 おすすめのカフェ情報 0.0011794464930089399
2 昨日の天気は雨でした 0.3641616533856764

🩺 ハマりどころと解決策(エラー別逆引き辞典)

ここからは、この手順の途中で筆者が実際に遭遇した多くのエラーと、その最終的な解決策を表にまとめます。

エラー内容 主な原因 解決策
ERROR 1064: ... near "VECTOR..." TiDBのバージョンが古いか、ベクトル機能が有効になっていないVECTOR型をサーバーが認識できない。 v8.4.0以降を使い、--db.configオプションで設定ファイルを読み込ませて起動する。
ERROR 1193: Unknown system variable 'tidb_enable_vector_search' 古いバージョンの設定変数を実行している。 このSETコマンドは不要。--db.configを使った起動方法に切り替える。
ERROR 1064: ... near "VECTOR)" VECTOR型の定義で、次元数と要素の型を省略している。 VECTOR<FLOAT>(1536)のように、必ず次元数と型を指定する。
ERROR 1105: vector has X dimensions, does not fit VECTOR(Y) 挿入するベクトルの次元数(X)と、テーブル定義の次元数(Y)が一致していない INSERT文の[]内の数値の個数が、テーブル定義の次元数と完全に一致しているか確認する。
ERROR 8027: Information schema is out of date ローカル環境でのリソース不足により、クラスタが不安定になっている。 1分ほど待ってから再実行する。頻発する場合はDockerのCPU/メモリ割り当てを増やすか、環境を再起動する。

まとめ

TiDBのベクトル検索機能を使えば、専門のベクトルデータベースを別途用意することなく、使い慣れたSQLで高度な類似検索機能をアプリケーションに組み込むことができます。

ローカルで試すにはv8.4.0以降と設定ファイルが必要というハマりどころはありますが、一度環境を構築すれば、VECTORデータ型とVEC_..._DISTANCE関数を覚えるだけで、TiDBが強力なAIバックエンドに進化します。ぜひ、未来の検索技術を体感してみてください!

コラボスタイル Developers

Discussion