RAGやベクトル検索を実装すると、Embeddingモデルが返す1536次元や3072次元のベクトルを、そのまま保存する必要があるのか疑問に感じることがあります。たとえば100万チャンクを3072次元で保存すると、Embedding本体だけでもかなりの容量になります。さらにHNSWなどのインデックスを作れば、実際に必要なストレージとメモリはさらに増えます。そこで検討できるのが、Embeddingの次元数を768や256などへ小さくする方法です。
次元数は小さくして構いません。ただし「小さいほどよい」わけではなく、検索精度を実データで評価して決める必要があります。
OpenAIのtext-embedding-3系は、次元を短縮して利用できるよう訓練されています。text-embedding-3-smallは標準1536次元、text-embedding-3-largeは標準3072次元ですが、dimensionsパラメータを指定してより小さなベクトルを生成できます。OpenAIは、大きなEmbeddingほど計算・メモリ・ストレージを多く消費するため、用途に応じて次元数を短縮できると説明しています。
Googleのgemini-embedding-2もMatryoshka Representation Learningを採用しており、標準3072次元から小さな次元へ切り詰められます。Googleは768、1536、3072次元を推奨値として挙げています。この記事では、Embeddingの次元数を小さくすると精度・保存容量・検索速度がどう変わるのか、OpenAI・Gemini・pgvectorを例に解説します。RAGの検索精度が低い原因を切り分ける方法はRAGの検索精度が低い原因|Embedding・チャンク・検索件数を順番に確認、チャンクサイズの決め方はRAGのチャンクサイズはいくつが正解?分割単位・オーバーラップを比較もあわせてご覧ください。
- Embeddingの次元数とは
- 次元数が多いほど必ず高精度になるわけではない
- Geminiでも768次元で高い性能を維持できる例がある
- 実務では768次元から試しやすい
- 次元数を半分にするとベクトル容量もほぼ半分になる
- 100万チャンクでは数GB単位で変わる
- 次元数を小さくするとメモリにも有利
- pgvectorでは3072次元をそのままHNSWにできない点に注意
- 1536次元ならpgvectorのvector型でHNSWを作れる
- OpenAIでEmbeddingを768次元にする
- APIのdimensionsを使わず自分でsliceしてよいか
- GeminiではoutputDimensionalityを指定する
- Gemini Embedding 2は縮小後も自動正規化される
- Embeddingモデルを変更したら既存ベクトルを作り直す
- 次元数を変更した場合も原則として再Embeddingする
- Embedding API料金は次元数だけでは安くならない
- halfvecなら精度を保ちながら容量を減らせる場合がある
- 次元数を決める前にチャンクを直したほうがよい場合もある
- 次元数はRecall@kで比較する
- Recall@kをTypeScriptで計算する
- 検索速度はp50とp95も測定する
- DB容量も実測する
- 256次元まで下げるのはありか
- 768次元がバランス候補になりやすい理由
- 最大次元を使ったほうがよいケース
- 次元数を小さくしたほうがよいケース
- 新規RAGなら次元数をどう決めるか
- 本番移行ではEmbedding設定をバージョン管理する
- よくある質問
- まとめ
Embeddingの次元数とは
Embeddingでは文章を数値の配列へ変換します。たとえば実際にはもっと長いものですが、イメージとしては次のようなデータです。
[0.0132, -0.0271, 0.0087, 0.0412, ...]
この配列に数値が1536個あれば1536次元、3072個あれば3072次元です。検索時には、質問から生成したEmbeddingと、DBへ保存してある各文書のEmbeddingを比較します。RAGではコサイン距離などを使い、質問に意味的に近いチャンクを検索します。OpenAIのEmbeddingガイドでも、検索ではクエリと文書のEmbedding間のコサイン類似度などを計算し、類似度の高い文書を取得する方法が紹介されています。
次元数が多いほど必ず高精度になるわけではない
3072次元より1536次元、1536次元より768次元のほうが情報量が少なくなるため、「最大次元を使わなければ精度が大きく落ちる」と考えるかもしれません。現在のEmbeddingモデルでは必ずしもそうとは限りません。OpenAIのtext-embedding-3系は、Embeddingの後ろ側を切り落として短縮しても概念表現を維持しやすいように訓練されています。
OpenAIは例として、text-embedding-3-largeを3072次元から256次元へ短縮しても、MTEBでは1536次元の旧text-embedding-ada-002を上回ったと説明しています。ここで注意したいのは、「256次元のtext-embedding-3-largeが1536次元のada-002を上回る」という結果が、「256次元のtext-embedding-3-largeが3072次元のtext-embedding-3-largeと同等」を意味するわけではないことです。Embeddingモデルそのものの性能差と、次元数による性能差は別に評価する必要があります。
Geminiでも768次元で高い性能を維持できる例がある
Googleも次元数別のMTEB結果を公開しています。gemini-embedding-001では2048次元のMTEBスコアが68.16、1536次元が68.17、768次元が67.99、512次元が67.55、256次元が66.19、128次元が63.31という結果が掲載されています。1536次元と768次元では差が小さい一方、128次元まで減らすと低下が大きくなっています。
ただし、これはGoogleが公開している特定モデル・特定ベンチマークでの結果です。自社の日本語FAQ検索・ソースコード検索・商品検索でも同じ差になるとは限りません。そのため「3072は無駄」「768なら絶対同じ」「256でも十分」とは判断せず、自分の検索データで比較します。
実務では768次元から試しやすい
次元数を減らしたい場合、いきなり128や256まで落とすより、中間値から比較する方法が扱いやすくなります。Gemini公式ドキュメントではgemini-embedding-2について768・1536・3072を推奨しています。モデル自体は128〜3072次元をサポートしています。
OpenAIではtext-embedding-3系のdimensionsパラメータによってEmbeddingを短縮できます。OpenAI自身も、ベクトルDBが1024次元までしか扱えないようなケースでは、text-embedding-3-largeを1024次元へ短縮する例を挙げています。RAGを新規構築するなら、256・768・1536・モデル標準値のように数パターンを用意し、同じ評価質問で検索精度を比較すると判断しやすくなります。特に容量削減を重視する場合は、まず768次元を比較対象にする方法があります。
次元数を半分にするとベクトル容量もほぼ半分になる
次元削減の効果が最も分かりやすく現れるのがストレージです。pgvectorのvector型では、ベクトル1件の保存容量は次の式です。
4 × dimensions + 8 bytes
各要素が32bitの単精度浮動小数点数なので、1次元につき4バイト使用します。pgvector公式ドキュメントでもこの計算式が明記されています。3072次元なら4×3072+8=12,296バイト、1536次元なら4×1536+8=6,152バイト、768次元なら4×768+8=3,080バイト、256次元なら4×256+8=1,032バイトまで小さくなります。つまり3072次元から768次元へ変更すると、Embedding本体の容量はおおよそ4分の1になります。
100万チャンクでは数GB単位で変わる
pgvectorのvector型だけを単純計算すると、100万Embeddingを保存した場合の容量は次の程度になります。
3072次元: 約12.30GB 1536次元: 約6.15GB 768次元: 約3.08GB 256次元: 約1.03GB
これはEmbedding本体だけを4 × dimensions + 8で計算した概算です。実際のPostgreSQLでは行ヘッダー・ページ管理・主キー・メタデータ・HNSW/IVFFlatインデックスなどが追加されるため、テーブル全体がこの容量に収まるわけではありません。pgvectorのHNSWも検索性能との引き換えにメモリを多く使用するインデックスです。それでも、数百万〜数千万チャンクを保存するサービスでは次元数の違いが大きく影響します。
次元数を小さくするとメモリにも有利
HNSWのようなANNインデックスでは、検索時に多数のベクトル候補を扱います。ベクトルが小さくなれば、同じ件数を扱うときに必要なベクトルデータ量も小さくなります。その結果、メモリやCPUキャッシュへ載せやすくなり、距離計算で処理する要素数も減らせます。
ただし、次元を半分にしても検索時間が必ず半分になるわけではありません。実際の検索時間には、HNSWのグラフ探索・ef_search・フィルタ・ディスクI/O・キャッシュヒット率・取得件数なども影響します。pgvectorでもHNSWのef_searchを高くするとRecallを改善できる代わりに検索速度が低下すると説明されています。次元数を変えたときは、検索精度だけでなく実際のp50・p95レイテンシも測定します。
pgvectorでは3072次元をそのままHNSWにできない点に注意
OpenAIのtext-embedding-3-largeは標準3072次元です。ここでpgvectorを使う場合に重要な制限があります。現在のpgvectorでは、vector型そのものには最大16,000次元を保存できますが、HNSWとIVFFlatでインデックスできるvector型は最大2,000次元です。halfvecなら最大4,000次元をHNSW・IVFFlatで扱えます。
そのため、3072次元を保存すること自体と、通常のvector型でHNSWインデックスを作ることは別問題です。
CREATE TABLE documents ( id BIGSERIAL PRIMARY KEY, embedding vector(3072) );
CREATE INDEX documents_embedding_hnsw ON documents USING hnsw (embedding vector_cosine_ops);
3072次元をpgvectorで利用するなら、halfvecを検討するか、Embedding生成時点で2000次元以下へ縮める方法があります。pgvector公式も2000次元を超える場合に、halfvec・半精度インデックス・バイナリ量子化・サブベクトル・次元削減などを選択肢として挙げています。
1536次元ならpgvectorのvector型でHNSWを作れる
OpenAIのtext-embedding-3-smallは標準1536次元なので、pgvectorのvector型HNSW上限2000次元以内に収まります。
CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE document_chunks ( id BIGSERIAL PRIMARY KEY, document_id BIGINT NOT NULL, content TEXT NOT NULL, embedding vector(1536) NOT NULL ); CREATE INDEX document_chunks_embedding_hnsw ON document_chunks USING hnsw (embedding vector_cosine_ops);
768次元へ下げるならDBスキーマも合わせます。
CREATE TABLE document_chunks_768 ( id BIGSERIAL PRIMARY KEY, document_id BIGINT NOT NULL, content TEXT NOT NULL, embedding vector(768) NOT NULL ); CREATE INDEX document_chunks_768_embedding_hnsw ON document_chunks_768 USING hnsw (embedding vector_cosine_ops);
Document側とQuery側で同じモデル・同じ次元数を使うことが前提です。
OpenAIでEmbeddingを768次元にする
OpenAIのtext-embedding-3モデルではdimensionsを指定します。
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
async function createEmbedding(text: string): Promise<number[]> {
const response = await openai.embeddings.create({
model: "text-embedding-3-large",
input: text,
dimensions: 768,
encoding_format: "float",
});
const embedding = response.data[0]?.embedding;
if (!embedding) {
throw new Error("Embeddingを取得できませんでした。");
}
if (embedding.length !== 768) {
throw new Error(`次元数が不正です: ${embedding.length}`);
}
return embedding;
}
OpenAIは、後から自分で配列を切り取る方法より、Embedding生成時にdimensionsパラメータを指定する方法を推奨しています。
APIのdimensionsを使わず自分でsliceしてよいか
Matryoshka型のEmbeddingでは先頭部分を利用できるため、次のように考えるかもしれません。
const reduced = fullEmbedding.slice(0, 768);
OpenAIは手動で次元を削減すること自体は可能としていますが、手動で切り詰める場合はL2正規化を行うよう案内しています。基本的にはAPIのdimensionsを利用する方法が推奨されています。新規Embeddingを生成できるのであれば、dimensions: 768を使うほうが分かりやすくなります。
GeminiではoutputDimensionalityを指定する
gemini-embedding-2ではoutputDimensionalityを指定します。
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({
apiKey: process.env.GEMINI_API_KEY,
});
async function createEmbedding(text: string): Promise<number[]> {
const response = await ai.models.embedContent({
model: "gemini-embedding-2",
contents: text,
config: {
outputDimensionality: 768,
},
});
const embedding = response.embeddings?.[0]?.values;
if (!embedding) {
throw new Error("Embeddingを取得できませんでした。");
}
if (embedding.length !== 768) {
throw new Error(`次元数が不正です: ${embedding.length}`);
}
return embedding;
}
Google公式ドキュメントでも同じoutputDimensionality: 768のJavaScript例が掲載されています。
Gemini Embedding 2は縮小後も自動正規化される
Geminiではモデル世代による違いにも注意が必要です。現在のgemini-embedding-2は、3072以外の次元へ縮小した場合も自動的に正規化します。一方、旧gemini-embedding-001では3072次元以外を指定した場合、手動で正規化する必要があります。Googleはこの違いを公式ドキュメントで明記しています。つまり、同じGeminiでもgemini-embedding-001とgemini-embedding-2では縮小Embeddingの扱いが異なります。モデルを移行するときは次元数だけでなく、正規化方法も確認します。
Embeddingモデルを変更したら既存ベクトルを作り直す
同じ768次元だからといって、別モデルで作ったEmbeddingを混在させてはいけません。たとえばgemini-embedding-001の768次元とgemini-embedding-2の768次元は配列長こそ同じですが、同じEmbedding空間ではありません。Googleもgemini-embedding-001とgemini-embedding-2のEmbedding空間には互換性がないため、移行時には既存データをすべて再Embeddingする必要があると説明しています。DBには次元数だけでなくモデル名も保存します。
ALTER TABLE document_chunks ADD COLUMN embedding_model VARCHAR(100) NOT NULL, ADD COLUMN embedding_dimensions INTEGER NOT NULL;
次元数を変更した場合も原則として再Embeddingする
本番DBが1536次元で動いている状態から768次元へ移行する場合、Queryだけを768次元へ変更してはいけません。既存Document EmbeddingとQuery Embeddingの次元が一致しなくなります。安全な移行では、新しいカラムまたは新しいテーブルを作り(例:document_chunks_v1を1536次元、document_chunks_v2を768次元として)、既存文書を新設定で再Embeddingしてから新インデックスへ登録し、評価したうえで検索先を切り替えます。問題があれば旧インデックスへ戻せます。
Embedding API料金は次元数だけでは安くならない
次元数を3072から768へ減らすと、Vector DBの保存容量や後段の計算量は減ります。しかし、OpenAIのEmbedding API料金まで4分の1になるわけではありません。OpenAIのEmbedding料金は入力トークン量を基準に計算されます。Embeddingガイドでもモデル料金は入力トークン単位として説明されています。同じ文章を3072次元と768次元でEmbeddingしても、入力文章のトークン数が同じなら、次元数削減によってAPIの入力料金が単純に4分の1になるわけではありません。次元削減によって削減しやすいのは、Vector DBのストレージ・インデックス容量・ネットワーク転送量・メモリ使用量・距離計算の負荷です。Embedding生成料金とVector DB運用コストは分けて考えます。
halfvecなら精度を保ちながら容量を減らせる場合がある
容量削減には、次元数を減らす以外の方法もあります。pgvectorには32bit浮動小数点のvector以外に、16bitのhalfvecがあります。vectorは4 × dimensions + 8バイトですが、halfvecは2 × dimensions + 8バイトです。1536次元なら、単純なベクトル部分の容量はhalfvecによっておおむね半分になります。さらにHNSW・IVFFlatでは、vectorが2000次元までなのに対してhalfvecは4000次元までインデックスできます。
そのため、「3072次元を768次元へ削減する」だけでなく、「3072次元を維持してhalfvecでインデックスする」という比較もできます。次元削減では意味表現の情報量を減らし、halfvecでは各値の数値精度を減らします。どちらが自分の検索で有利かは実測します。
次元数を決める前にチャンクを直したほうがよい場合もある
RAGの検索精度が悪い原因をEmbeddingの次元数だけで説明できるとは限りません。たとえば、返品規約・配送方法・会員登録・決済方法という複数テーマを1つの巨大チャンクへまとめている場合、Embeddingを3072次元へ増やしても検索精度が十分に改善しない可能性があります。反対に、意味のまとまりごとに適切にチャンク分割できていれば、より小さなEmbeddingでも必要な文書を上位へ取得できる可能性があります。検索精度そのものが低い場合は、次元数を疑う前にRAGの検索精度が低い原因|Embedding・チャンク・検索件数を順番に確認で紹介している手順で切り分けることをおすすめします。次元数を比較するときは、チャンクサイズ・Embeddingモデル・検索方式・top_kなどを固定します。複数の設定を同時に変更すると、何によって精度が変化したのか分からなくなります。
次元数はRecall@kで比較する
RAGなら、最終的な回答文だけを見て次元数を決めないほうがよいでしょう。まず検索だけを評価します。たとえば100件の評価質問について、正解チャンクをあらかじめ登録します。
type EvaluationCase = {
query: string;
relevantDocumentIds: string[];
};
各次元数で同じ検索を実行し、Recall@5などを比較します。たとえば768次元でRecall@5が0.94、1536次元で0.945のようにほとんど差がなく、768次元の検索速度と容量が大幅に有利なら、768を採用する判断ができます。逆に256次元にしたことで専門用語や似た文書の区別が悪化するなら、容量削減より精度を優先します。
Recall@kをTypeScriptで計算する
次元数比較用に、簡単なRecall@kを実装できます。
type RetrievalResult = {
id: string;
score: number;
};
type RetrievalTestCase = {
relevantIds: string[];
results: RetrievalResult[];
};
function recallAtK(testCase: RetrievalTestCase, k: number): number {
const relevant = new Set(testCase.relevantIds);
if (relevant.size === 0) {
return 0;
}
const topK = testCase.results.slice(0, k);
const found = new Set(
topK.map((result) => result.id).filter((id) => relevant.has(id)),
);
return found.size / relevant.size;
}
function averageRecallAtK(cases: RetrievalTestCase[], k: number): number {
if (cases.length === 0) {
return 0;
}
const total = cases.reduce(
(sum, testCase) => sum + recallAtK(testCase, k),
0,
);
return total / cases.length;
}
次元数ごとに同じ評価セットを実行します。
検索速度はp50とp95も測定する
次元削減の目的が高速化なら、Recallだけでは不十分です。各検索の処理時間を保存します。
type SearchBenchmark = {
dimensions: number;
query: string;
latencyMs: number;
recallAt5: number;
};
100回以上の検索を実行し、p50・p95・p99を比較します。平均値だけでは、特定クエリで極端に遅くなる問題を見つけにくくなります。またHNSWではef_searchによってRecallと検索速度が変化します。pgvectorではef_searchの標準値が40で、高くするとRecallが改善する代わりに速度が低下します。したがって次元数比較中は、ef_searchも固定します。
SET hnsw.ef_search = 100;
DB容量も実測する
理論上のEmbedding容量だけではなく、PostgreSQL上の実サイズも確認します。
SELECT pg_size_pretty(pg_total_relation_size('document_chunks_768'));
インデックスだけを確認します。
SELECT pg_size_pretty(pg_relation_size('document_chunks_768_embedding_hnsw'));
1536次元と768次元のテーブルを同じ件数で作り、検索精度・検索レイテンシ・テーブル容量・HNSW容量・インデックス構築時間を比較すると、次元削減の効果を判断しやすくなります。
256次元まで下げるのはありか
ありですが、評価なしで本番採用するのは避けたほうがよいでしょう。OpenAIはtext-embedding-3-largeの256次元版が旧text-embedding-ada-002の1536次元版をMTEBで上回る例を公開しています。Googleのgemini-embedding-001の公開結果でも、256次元はMTEB 66.19で、768次元の67.99より低いものの、実用にならないほど性能が失われるという結果ではありません。128次元まで下げると63.31まで低下しています。
ただし、自社データでは差の出方が変わります。数千万件を扱い、1ベクトル数KBの差が非常に重要なら256次元を積極的に評価する価値があります。数万件しかなく、検索精度を最優先するなら、無理に256まで落とすメリットは小さくなります。
768次元がバランス候補になりやすい理由
768次元は、容量削減と精度維持を比較しやすい中間点です。3072次元からならEmbedding本体は約4分の1、1536次元からなら約半分になります。GoogleもGemini Embeddingで768を推奨次元の一つとして挙げています。またpgvectorのvector型HNSW上限2000次元を十分下回るため、通常の32bitベクトルとして扱えます。だからといって、すべてのRAGで768が正解という意味ではありません。最初の比較候補として扱うのが適切です。
最大次元を使ったほうがよいケース
検索精度のわずかな低下も避けたい用途では、最大次元を維持する価値があります。文書件数が少なくストレージコストが問題にならない場合も、無理に削減する必要はありません。また、非常に似た文書を細かく区別する検索・専門用語が多い検索・多言語検索などでは、次元削減による順位変化を慎重に評価します。OpenAI自身も次元削減について、より小さなベクトルと引き換えに多少の精度をトレードオフするものとして説明しています。最大次元を基準値として残し、そこからどこまで縮めても品質要件を満たすか調べる方法が安全です。
次元数を小さくしたほうがよいケース
数百万〜数千万件のEmbeddingを保存する場合は、次元削減の効果が大きくなります。Vector DBの料金が容量やメモリに強く影響されるサービスでも検討価値があります。また、pgvectorのようにANNインデックス側に次元数制限がある場合、モデル標準の次元数をそのまま利用できないことがあります。モバイル端末やEdge環境へEmbeddingを配布する場合も、小さいベクトルのほうが転送量とメモリを減らせます。重要なのは「ストレージを減らしたいから256にする」ではなく、「品質要件を満たす最小の次元数を探す」という考え方です。
新規RAGなら次元数をどう決めるか
新しいRAGを構築するなら、最初から一つの次元へ固定しないほうがよいでしょう。たとえばモデル標準値を基準として、768次元と256次元を追加します(baseline: モデル標準次元、candidate A: 768次元、candidate B: 256次元)。チャンク・検索クエリ・HNSW設定・top_kを同じにして評価します。そのうえで、Recall@5・MRR・検索p95・DB容量・HNSW容量・インデックス構築時間を比較します。検索品質の差がほとんどなければ小さい次元を選びます。品質差が大きければ一段階戻します。RAG全体の実装はRAG完全実装ガイド【TypeScript】で解説しています。
本番移行ではEmbedding設定をバージョン管理する
Embedding設定はコード内の定数だけにしないほうが安全です。DBへ次のような情報を記録します。
type EmbeddingConfiguration = {
provider: "openai" | "gemini";
model: string;
dimensions: number;
normalization: "provider" | "application";
distance: "cosine" | "inner_product" | "l2";
version: string;
};
次元数やモデルを変更した場合はembedding-v4として新しいインデックスを構築します。RAGの検索結果が変わったときに、どのEmbedding設定で生成されたデータか追跡できます。
よくある質問
Q1536次元から768次元にすると精度は半分になりますか?
Aなりません。次元数と検索精度は比例関係ではありません。Matryoshka Representation Learningなどを利用した現在のEmbeddingモデルでは、先頭の小さな次元だけでも意味表現を維持しやすいよう訓練されています。Googleが公開しているgemini-embedding-001のMTEBでも1536次元が68.17、768次元が67.99となっており、次元が半分でも性能が半分になるわけではありません。
Q次元数を減らすとEmbedding API料金も安くなりますか?
AOpenAIの場合、Embedding API料金は入力トークン量を基準にしています。そのため同じ文章を3072次元から768次元へ変更しても、生成料金が単純に4分の1になるわけではありません。主な削減効果はVector DBの容量・メモリ・転送量・検索時の計算負荷です。
Qpgvectorで3072次元を使えますか?
A保存自体は可能です。現在のpgvectorのvector型は最大16,000次元を保存できます。ただしHNSW・IVFFlatでvector型をインデックスできるのは最大2000次元です。halfvecなら4000次元までインデックスできます。text-embedding-3-largeの標準3072次元を使う場合は、この違いに注意が必要です。
QOpenAIの3072次元を1536次元にしてもよいですか?
Atext-embedding-3-largeはdimensionsを指定して短縮できます。OpenAIはこのモデルを、次元を短縮して性能とコストをトレードオフできるよう訓練していると説明しています。ただし、自社データで標準3072次元との検索精度を比較してから採用します。
QGeminiは768次元でよいですか?
AGoogleはgemini-embedding-2について768・1536・3072を推奨次元として挙げています。768は有力な比較候補ですが、すべての用途で最適という意味ではありません。
Q次元数を変えたら既存DBをそのまま使えますか?
AQueryだけ次元を変えることはできません。既存Document Embeddingも同じ設定で作り直し、新しいベクトルインデックスを構築します。また、同じ次元数でもEmbeddingモデルが変わればEmbedding空間が異なる場合があります。Googleもgemini-embedding-001からgemini-embedding-2への移行では全データを再Embeddingする必要があると説明しています。
まとめ
Embeddingの次元数は、モデル標準値を必ずそのまま使う必要はありません。OpenAIのtext-embedding-3-smallは標準1536次元、text-embedding-3-largeは標準3072次元ですが、dimensionsを使って小さくできます。OpenAIは次元短縮によって、精度とのトレードオフで計算量・メモリ・ストレージを減らせるよう設計しています。
Gemini EmbeddingもMRLによる次元削減に対応しており、現在のgemini-embedding-2では128〜3072次元を指定できます。Googleは768・1536・3072を推奨しています。pgvectorの32bitvector型では、1件のEmbedding容量は4 × dimensions + 8バイトです。そのため100万件なら3072次元でEmbedding本体が約12.30GB、768次元なら約3.08GBまで減ります。さらにpgvectorでは、HNSW・IVFFlatでvector型をインデックスできる上限が2000次元なので、3072次元のモデルでは次元削減やhalfvecを検討する理由にもなります。
ただし、容量を減らせるからといって、いきなり128や256次元へ固定するのは避けます。まずモデル標準値をベースラインにし、768・256などの候補を同じチャンク・同じ検索条件で比較します。最終的には、検索精度を満たしたうえで、その中で最も小さい次元を選ぶという考え方が適しています。RAGならRecall@kやMRR・検索p95・HNSWインデックス容量まで測定し、「最大次元だから安心」でも「小さいほど速い」でもなく、必要な検索品質を維持できる最小次元を採用することが重要です。

