Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MySQL9でベクトルカラム登場!PHP×AWSでのAI/類似検索はこう変わる

 MySQL9でベクトルカラム登場!PHP×AWSでのAI/類似検索はこう変わる

MySQL9でのベクトルカラム/ベクトル検索サポートは、PHPアプリケーションにおけるAI活用や類似性検索を大きく変える可能性を秘めています。
プロポーザル提出時は、AWSのRDSで取り扱い可能なバージョンは、8系が最新ですが、特にAWS (RDS/Aurora) 環境での利用が現実味を帯びる中、そのインパクトは計り知れません。
本セッションは、ミドルレベルのPHPエンジニアを対象に、この「ベクトルカラム」導入に焦点を絞ります。ベクトルデータの基本的な概念から、MySQL9で予想されるベクトル型・専用インデックス・検索関数の概要、そしてPHPからこれらをどう扱うか、パフォーマンス考慮点、AWS環境特有の設定や制約についてを説明します。推薦システム、画像検索、セマンティック検索といった機能の実装がどう変化するのか?何を学び、どう備えるべきか? 未来のキラー機能開発に向けた勘所をお伝えします。

Avatar for Suguru Ohki

Suguru Ohki

July 18, 2025
Tweet

More Decks by Suguru Ohki

Other Decks in Programming

Transcript

  1. 2

  2. 従来手法の限界を実際の検索結果で検証 ECサイトっぽいデータベースでテスト テストデータ(商品マスタ) -- 実際の商品データ例 INSERT INTO products (name, description,

    price) VALUES ('赤いワンピース', '鮮やかな赤色のエレガントなワンピース', 12800), ('クリムゾンドレス', '深紅色の上品なパーティードレス', 15600), ('真紅のワンピース', '美しい真紅色のフォーマルワンピース', 18900), ('ルビーレッドワンピース', '宝石のような赤色のワンピース', 22400), ('ワインレッドドレス', '落ち着いたワインレッドのドレス', 16800), ('スカーレットワンピース', 'スカーレット色のカジュアルワンピース', 9800); 16
  3. 従来手法の限界を実際の検索結果で検証 LIKE検索の場合 検索結果(実際のデータ例) 商品名 価格 検索結果 理由 赤いワンピース ¥12,800 ヒット

    完全一致 クリムゾンドレス ¥15,600 ヒットしない 「赤い」が含まれない 真紅のワンピース ¥18,900 ヒットしない 「赤い」が含まれない ルビーレッドワンピース ¥22,400 ヒットしない 「赤い」が含まれない 結果: 6商品中1商品のみヒット(検索成功率: 16.7%) 問題: 完全一致する文字列のみ検索、同義語を認識できない 18
  4. 従来手法の限界を実際の検索結果で検証 全文検索の場合 -- 全文検索インデックスを作成 ALTER TABLE products ADD FULLTEXT(name, description);

    -- 検索実行 SELECT name, price, description FROM products WHERE MATCH(name, description) AGAINST('赤い ワンピース' IN BOOLEAN MODE); 19
  5. 従来手法の限界を実際の検索結果で検証 全文検索の場合 検索結果(実際のデータ例) 商品名 価格 説明文 検索結果 スコ ア 赤いワンピース

    ¥12,800 鮮やかな赤色のエレガント なワンピース ヒット 2.1 真紅のワンピー ス ¥18,900 美しい真紅色のフォーマル ワンピース 「ワンピース」の みヒット 0.8 結果: 6商品中3商品ヒット(検索成功率: 50%)、しかし関連性の低い結果も含む 問題: 単語の部分一致はできるが、意味的関連性は理解できない 20
  6. ベクトル検索について検証 ベクトル検索の場合 検索結果(実際のベクトル類似度計算) 商品名 価格 類似度スコ ア 検索結 果 理由

    赤いワンピース ¥12,800 0.98 ヒッ ト 完全一致 真紅のワンピース ¥18,900 0.92 ヒッ ト 「真紅」=「赤い」を理解 結果: 6商品中6商品すべてヒット(検索成功率: 100%) 特徴: 意味的な類似性を理解し、関連する商品をすべて発見 24
  7. ベクトル検索について検証 ベクトル検索の場合 検索結果(実際のベクトル類似度計算) ベクトル検索の優位性 同義語・類義語を自動的に認識(赤い ≈ クリムゾン ≈ 真紅 ≈

    ルビーレッド) 関連概念の理解(ワンピース ≈ ドレス) 類似度スコアによる関連性の定量化 ユーザーの意図に最も近い結果を提供 25
  8. 結果:ユーザーの期待に応えられない検索体験 想定されるユーザー行動 検索失敗の影響 検索結果0件 → ユーザーが離脱 関連性の低い結果 → ユーザーが再検索 3回目の検索失敗

    → ユーザーがサイト離脱 ビジネスへの影響 機会損失: 月間売上のが数十%実は取れてないなどがある 顧客満足度低下: サブスクリプションの場合は継続率に直結 競合他社への流出: そのまま同じ予算を切り替えるだけなので簡単 27
  9. 1. テキストを数値(ベクトル)化するモデル MLのモデルを使ってテキストを数値化(ベクトル)する テキスト → ベクトル(数値の配列) 「赤いワンピース」→ [0.1, -0.5, 0.3,

    ..., 0.2] 「クリムゾンドレス」→ [0.15, -0.48, 0.31, ..., 0.18] 言葉の意味を数値(ベクトル)で表現する ※このベクトルは言語ごとに違います。テストに出るよ! (i18n対応に影響あり) 36
  10. 2. ベクトルを保存するストレージ テキストではなく、ベクトルで保存するストレージが必要 機能 PostgreSQL + pgvector MySQL 9 標準サーバー

    距離計算 完全サポート HeatWave専用 インデックス HNSW/IVFFlat 作成不可 最大次元数 16,000 16,383 類似度検索 高速 アプリ層で実装必要 37
  11. 3. クエリとストレージから類似度を計算する処理 機能 PostgreSQL + pgvector MySQL 9 標準サーバー 距離計算

    完全サポート HeatWave専用 インデックス HNSW/IVFFlat 作成不可 最大次元数 16,000 16,383 類似度検索 高速 アプリ層で実装必要 MySQL9のVECTOR型が大敗である・・・。 ※ CloudSQL for MySQLであれば、ベクトルカラムにインデックスが貼れますが、それでも 類似度計算は実装の必要があり、大敗。 38
  12. ベクトル化プロセス詳解 テキスト→ベクトル変換実装 class TextEmbedding { private $apiKey; private $model =

    'text-embedding-3-small'; public function embed($text) { $url = 'https://api.openai.com/v1/embeddings'; $data = [ 'model' => $this->model, 'input' => $text, 'encoding_format' => 'float' ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); // POSTデータ curl_setopt($ch, CURLOPT_HTTPHEADER, [ // HTTPヘッダー 'Authorization: Bearer ' . $this->apiKey, 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl exec($ch); 51
  13. MySQL9 テーブル設計 CREATE TABLE products ( id INT PRIMARY KEY,

    name VARCHAR(255), description TEXT, description_vector VECTOR(1536) -- text-embedding-3-small次元 ); VECTOR型の特徴 データ型: 各エントリは4byte浮動小数点値 サイズ制限: デフォルト長:2048、最大:16383 制約: キーとして使用不可(PRIMARY/FOREIGN/UNIQUE) 操作: 比較は等価性のみ 52
  14. データ挿入実装 public function insertProduct($name, $description) { $vectorString = $this->embedding->embedToVectorString($description); $sql

    = "INSERT INTO products (name, description, description_vector) VALUES (?, ?, STRING_TO_VECTOR(?))"; $stmt = $this->pdo->prepare($sql); $stmt->execute([$name, $description, $vectorString]); } STRING_TO_VECTOR関数 文字列 "[1.05, -17.8, 32]" → バイナリVECTOR 標準MySQL9で利用可能 逆変換はVECTOR_TO_STRING() 53
  15. 類似度検索実装(PHPで計算) 1. クエリのベクトル化と全データ取得 public function searchSimilar($query, $limit = 10) {

    // 1. クエリをベクトル化 $queryVector = $this->embedding->embed($query); // 2. 全ベクトル取得 $sql = "SELECT id, name, description_vector FROM products"; $stmt = $this->pdo->query($sql); $products = $stmt->fetchAll(); 54
  16. 類似度検索実装(PHPで計算) 2. コサイン類似度の計算とソート // 3. コサイン類似度計算 $similarities = []; foreach

    ($products as $product) { $vectorBinary = $product['description_vector']; $productVector = $this->binaryToFloatArray($vectorBinary); $similarity = $this->cosineSimilarity($queryVector, $productVector); $similarities[] = [ 'id' => $product['id'], 'name' => $product['name'], 'similarity' => $similarity ]; } // 4. 類似度でソート usort($similarities, function($a, $b) { // PHP標準ソート関数 return $b['similarity'] <=> $a['similarity']; 55
  17. コサイン類似度計算 private function cosineSimilarity($a, $b) { $dotProduct = 0; $normA

    = 0; $normB = 0; for ($i = 0; $i < count($a); $i++) { $dotProduct += $a[$i] * $b[$i]; $normA += $a[$i] * $a[$i]; $normB += $b[$i] * $b[$i]; } return $dotProduct / (sqrt($normA) * sqrt($normB)); } private function binaryToFloatArray($binary) { // バイナリVECTORを浮動小数点配列に変換 $floats = []; for ($i = 0; $i < strlen($binary); $i += 4) { $floats[] = unpack('f', substr($binary, $i, 4))[1]; } return $floats; } 56
  18. 63

  19. 2. 拡張機能の有効化 -- データベースに接続後、pgvectorを有効化 CREATE EXTENSION vector; -- 確認 SELECT

    extversion FROM pg_extension WHERE extname = 'vector'; 3. Ubuntu/Debianでの手動インストール Copy# PostgreSQL開発ファイルとpgvectorのインストール sudo apt install postgresql-server-dev-17 sudo apt install postgresql-17-pgvector または手動コンパイル git clone --branch v0.8.0 https://github.com/pgvector/pgvector.git cd pgvector make sudo make install 74
  20. 基本的な使用方法 1. テーブル作成とデータ挿入 -- ベクトルテーブルの作成 CREATE TABLE documents ( id

    SERIAL PRIMARY KEY, title TEXT, content TEXT, embedding vector(1024) -- 1024次元のベクトル ); -- ベクトルデータの挿入 INSERT INTO documents (title, content, embedding) VALUES ('文書1', '人工知能について', '[0.1, 0.2, 0.3, ...]'), ('文書2', '機械学習の基礎', '[0.4, 0.5, 0.6, ...]'); -- 文字列からベクトルへの変換も可能 INSERT INTO documents (embedding) VALUES (string_to_vector('[1.0, 2.0, 3.0]')), (cast('[4.0, 5.0, 6.0]' as vector)); 75
  21. 2. ベクトル検索の実行 -- コサイン類似度による検索 SELECT title, content, 1 - (embedding

    <=> '[0.2, 0.3, 0.4, ...]') AS cosine_similarity FROM documents ORDER BY cosine_similarity DESC LIMIT 5; -- 内積による検索(正規化済みベクトルの場合に最適) SELECT title, content, (embedding <#> '[0.2, 0.3, 0.4, ...]') * -1 AS inner_product FROM documents ORDER BY inner_product DESC LIMIT 5; 77
  22. 3. 距離関数の種類 -- <-> : L2距離(ユークリッド距離) -- <#> : 負の内積

    -- <=> : コサイン距離 -- <+> : L1距離(マンハッタン距離) -- <~> : ハミング距離(バイナリベクトル用) -- <%> : ジャカード距離(バイナリベクトル用) -- 関数形式でも利用可能 SELECT l2_distance(embedding, '[1,2,3]') AS euclidean, cosine_distance(embedding, '[1,2,3]') AS cosine, inner_product(embedding, '[1,2,3]') AS dot_product FROM documents; 78
  23. 高性能インデックスの作成 1. HNSWインデックス(推奨) -- L2距離用HNSWインデックス CREATE INDEX ON documents USING

    hnsw (embedding vector_l2_ops); -- コサイン距離用HNSWインデックス CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops); -- 内積用HNSWインデックス CREATE INDEX ON documents USING hnsw (embedding vector_ip_ops); -- パラメータ調整版 CREATE INDEX ON documents USING hnsw (embedding vector_l2_ops) WITH (m = 16, ef_construction = 64); 79
  24. 2. IVFFlatインデックス -- データが十分蓄積されてから作成 CREATE INDEX ON documents USING ivfflat

    (embedding vector_l2_ops) WITH (lists = 100); -- リスト数の目安: -- ~100万行: rows / 1000 -- 100万行超: sqrt(rows) 80
  25. 3. 検索パフォーマンスの調整 -- HNSW検索精度の調整 SET hnsw.ef_search = 100; -- デフォルト40

    -- IVFFlat検索範囲の調整 SET ivfflat.probes = 10; -- デフォルト1 -- トランザクション内での一時設定 BEGIN; SET LOCAL hnsw.ef_search = 200; SELECT * FROM documents ORDER BY embedding <-> '[...]' LIMIT 10; COMMIT; 81
  26. 実践的な応用例 1. フィルタリングとの組み合わせ -- カテゴリフィルタとベクトル検索の組み合わせ CREATE INDEX ON documents (category_id);

    -- フィルタ用インデックス -- 効率的な検索 SELECT * FROM documents WHERE category_id = 123 ORDER BY embedding <-> '[...]' LIMIT 5; -- フィルタリング専用の部分インデックス CREATE INDEX ON documents USING hnsw (embedding vector_l2_ops) WHERE category_id = 123; 82
  27. 2. ハイブリッド検索(全文検索+ベクトル検索) -- 全文検索インデックスも作成 CREATE INDEX ON documents USING gin(to_tsvector('english',

    content)); -- ハイブリッド検索の実装 WITH vector_results AS ( SELECT id, title, embedding <-> '[...]' AS vec_distance FROM documents ORDER BY vec_distance LIMIT 20 ), text_results AS ( SELECT id, title, ts_rank_cd(to_tsvector('english', content), query) AS text_score FROM documents, plainto_tsquery('english', 'machine learning') query WHERE to_tsvector('english', content) @@ query ORDER BY text_score DESC LIMIT 20 ) -- Reciprocal Rank Fusionで結合 SELECT * FROM vector_results UNION SELECT * FROM text_results; 83
  28. 3. メモリ使用量の最適化 -- 半精度ベクトルでメモリ使用量を半減 CREATE TABLE efficient_docs ( id SERIAL

    PRIMARY KEY, title TEXT, embedding halfvec(1024) -- 半精度ベクトル ); -- 半精度でのインデックス作成 CREATE INDEX ON efficient_docs USING hnsw (embedding halfvec_l2_ops); -- バイナリ量子化でさらなる圧縮 CREATE INDEX ON documents USING hnsw ((binary_quantize(embedding)::bit(1024)) bit_hamming_ops); 84
  29. 1. PostgreSQL設定の最適化 # postgresql.conf shared_buffers = 25% of RAM maintenance_work_mem

    = 2GB # インデックス作成用 max_parallel_workers_per_gather = 4 max_parallel_maintenance_workers = 4 86
  30. 2. インデックス作成の最適化 -- インデックス作成の高速化 SET maintenance_work_mem = '8GB'; SET max_parallel_maintenance_workers

    = 7; -- 本番環境では同時実行インデックス作成 CREATE INDEX CONCURRENTLY idx_vector ON documents 3. 監視とチューニング -- インデックス使用状況の確認 EXPLAIN ANALYZE SELECT * FROM documents ORDER BY embedding <-> '[...]' LIMIT 5; -- インデックスサイズの確認 SELECT pg_size_pretty(pg_relation_size('idx_vector')); 87
  31. 1. スパースベクトル -- スパースベクトルテーブル CREATE TABLE sparse_data ( id SERIAL

    PRIMARY KEY, sparse_vec sparsevec(1000) ); -- スパースベクトルの挿入({index:value}/dimensions形式) INSERT INTO sparse_data (sparse_vec) VALUES ('{1:1.0, 10:2.0, 100:3.0}/1000'), ('{5:4.0, 50:5.0, 500:6.0}/1000'); 89
  32. 2. バイナリベクトル -- バイナリベクトル(画像ハッシュなど) CREATE TABLE image_hashes ( id SERIAL

    PRIMARY KEY, image_hash bit(64) ); -- ハミング距離による検索 SELECT * FROM image_hashes ORDER BY image_hash <~> '1010101010101010...' LIMIT 5; 90
  33. 92

  34. ベクトル距離の視覚的理解 2次元空間でのベクトル距離 %%{init: {'theme': 'base', 'themeVariables': { 'background': 'transparent', 'primaryColor':

    'transparent', 'primaryBorderColor': '#ffffff', 'primaryTextColor': '#ffffff', 'lineColor': '#ffffff', 'arrowheadColor': '#ffffff', 'edgeLabelBackground': '#3D3D5C' }}}%% graph LR subgraph "2次元ベクトル空間" O[原点 (0,0)] A["赤いワンピース (0.8, 0.6)"] B["クリムゾンドレス (0.75, 0.65)"] C["青いTシャツ 93
  35. コサイン類似度の視覚的理解 ベクトル間の角度 = 意味の類似性 %%{init: {'theme': 'base', 'themeVariables': { 'background':

    'transparent', 'primaryColor': 'transparent', 'primaryBorderColor': '#ffffff', 'primaryTextColor': '#ffffff', 'lineColor': '#ffffff', 'arrowheadColor': '#ffffff', 'edgeLabelBackground': '#3D3D5C' }}}%% graph TD subgraph "コサイン類似度の概念" O[原点] A["ベクトルA 「赤いワンピース」"] B["ベクトルB 「クリムゾンドレス」"] C["ベクトルC 94
  36. 95

  37. テキストをベクトルに変換するとは? Embeddingの概念 Embedding(埋め込み) とは、テキストを多次元の数値ベクトルに変換する技術 「赤いワンピース」→ [0.1, -0.5, 0.3, ..., 0.2]

    (1536次元) 意味的に近い言葉は、ベクトル空間で近い位置に配置される 人間には理解しづらいが、コンピュータで扱いやすい形式 96
  38. 「赤いワンピース」のベクトル変換プロセス ステップ1: テキスト入力 入力テキスト 「赤いワンピース」 AIモデルの理解プロセス 1. 単語分解: 「赤い」+ 「ワンピース」

    2. 意味解析: 色(赤)+ 衣服(ワンピース) 3. 文脈理解: 女性用衣服、ファッション、色彩 4. 関連概念: エレガント、フォーマル、カジュアル 97
  39. ステップ2: ベクトル変換(実際の数値例) OpenAI text-embedding-3-small による変換結果 実際のベクトル値(一部抜粋) 「赤いワンピース」→ [ 0.0234, //

    色彩関連の次元 -0.1567, // 衣服関連の次元 0.0891, // 女性用品関連の次元 0.2134, // ファッション関連の次元 -0.0456, // フォーマル度関連の次元 ... // 1536次元まで続く 0.1789 ] ベクトルの特徴 次元数: 1536次元(text-embedding-3-small) 98
  40. ステップ3: 類似商品のベクトル比較 実際の数値を使った類似度計算 各商品のベクトル値(簡略化した5次元で説明) 商品名 次元1 次元2 次元3 次元4 次元5

    赤いワンピース 0.023 -0.157 0.089 0.213 -0.046 クリムゾンドレス 0.031 -0.149 0.095 0.198 -0.052 真紅のワンピース 0.028 -0.162 0.087 0.221 -0.041 青いTシャツ -0.156 -0.089 0.034 0.067 0.123 コサイン類似度の計算例 「赤いワンピース」vs「クリムゾンドレス」 99
  41. ステップ4: 類似度ランキングの生成 計算結果による商品ランキング 「赤いワンピース」との類似度ランキング 順位 商品名 類似度スコア 解釈 1位 赤いワンピース

    1.00 完全一致(同じ商品) 2位 真紅のワンピース 0.92 非常に類似(色+形状) 3位 クリムゾンドレス 0.89 高い類似性(色+関連形状) 4位 ルビーレッドワンピース 0.85 高い類似性(色+形状) 5位 ワインレッドドレス 0.78 中程度の類似性(色系統) 6位 赤色のスカート 0.65 中程度の類似性(色のみ) 7位 青いTシャツ 0.21 低い類似性(異なる色) 100
  42. ベクトル変換の仕組み なぜベクトルに変換するのか? %%{init: {'theme': 'base', 'themeVariables': { 'background': 'transparent', 'primaryColor':

    'transparent', 'primaryBorderColor': '#ffffff', 'primaryTextColor': '#ffffff', 'lineColor': '#ffffff', 'arrowheadColor': '#ffffff', 'edgeLabelBackground': '#3D3D5C' }}}%% graph LR A["テキスト '赤いワンピース'"] -->|AIモデル| B["ベクトル [0.023, -0.157, ...]"] C["テキスト 'クリムゾンドレス'"] -->|AIモデル| D["ベクトル [0.031, -0.149, ...]"] E["テキスト 101
  43. ベクトルの類似度計算 コサイン類似度の直感的理解 計算式 cos(θ) = (A・B) / (|A| × |B|)

    値の意味 1.0: 完全に同じ意味 0.7~0.9: かなり類似 0.5~0.7: ある程度類似 0.5未満: 関連性が低い 例:「赤いワンピース」との類似度 クリムゾンドレス: 0.85 真紅のワンピース: 0.92 赤色のスカート: 0.73 青いTシャツ: 0.21 102
  44. ベクトル検索実現のために必要なステップ 1. 単語/文章 → 数値の配列(ベクトルにする = 埋め込み) 2. 類似度 =

    ベクトル計算(コサイン類似度やユークリッド距 離など) 3. AI埋め込みモデルの活用 (コサイン類似度なんて高校の数学以来くらいで聞く人も多いのでは・・・) 103
  45. ベクトル検索に必要なものは、次の3つ 1. テキストをベクトルに変換するための機構 → ライブラリや OpenAPI Embedding API 2. ベクトルを保管するためのカラム

    → VECTOR型のDatabase のカラムなど 3. ベクトルの意味的な距離を計算するための機能 → DISTANCE関数やアプリケーション実装 104
  46. バッチ処理で効率化 なぜバッチ処理が重要? 単一リクエスト方式の問題点 graph LR A[商品1] -->|API呼出1| B[ベクトル1] C[商品2] -->|API呼出2|

    D[ベクトル2] E[商品3] -->|API呼出3| F[ベクトル3] style A fill:#f9f,stroke:#333,stroke-width:2px style C fill:#f9f,stroke:#333,stroke-width:2px style E fill:#f9f,stroke:#333,stroke-width:2px 課題: 1000商品 = 1000回のAPI呼び出し → 高コスト・低速 105
  47. バッチ処理の実装 embedBatch()メソッド public function embedBatch($texts) { $data = [ 'model'

    => $this->model, 'input' => $texts, // 配列で一括送信 'encoding_format' => 'float' ]; // APIリクエスト処理... $result = json_decode($response, true); $embeddings = []; foreach ($result['data'] as $item) { $embeddings[] = '[' . implode(',', $item['embedding']) . ']'; } ポイント: input に配列を渡すことで複数テキストを一括処理 106
  48. HeatWave vs 標準MySQL 項目 標準MySQL HeatWave VECTOR型 利用可能 利用可能 距離計算

    PHP実装 DISTANCE関数 パフォーマンス 中小規模で実用的 大規模で高速 コスト 低い 高い 環境 どこでも クラウド限定 HeatWaveの例 SELECT name, DISTANCE(description_vector, ?, "COSINE") as similarity FROM products ORDER BY similarity LIMIT 10; 110
  49. ユースケース別推奨事項 データ規模・予算・技術レベル別の選択指針 シナリオ データ規模 予算 推奨アプローチ 理由 スタートアップ ~10万件 低

    標準MySQL + PHP 初期コスト抑制、柔軟性 中規模EC ~100万件 中 標準MySQL + 最適化 バランス重視 大規模サービス 1000万件+ 高 HeatWave パフォーマンス最優先 実験・検証 任意 低 標準MySQL + PHP 学習コスト最小 111
  50. 次のステップガイド 開発者向け 1. 環境構築: MySQL 9の検証環境セットアップ 2. プロトタイプ作成: 小規模データでの動作確認 3.

    パフォーマンステスト: 実データでの性能評価 意思決定者向け 1. ROI分析: 検索改善による売上向上の試算 2. コスト比較: 開発・運用コストの詳細見積もり 3. 段階的導入計画: リスクを抑えた導入戦略 112
  51. パフォーマンス最適化戦略 キャッシュ戦略 // クエリベクトルのキャッシュ $cacheKey = 'vector_' . md5($query); $queryVector

    = $this->cache->get($cacheKey); if (!$queryVector) { $queryVector = $this->embedding->embed($query); $this->cache->set($cacheKey, $queryVector, 3600); } 113