PostgreSQL のベクトル検索のインデックス作成方法のメモ。
ベクトルカラムにインデックスを張ることで、高速にベクトル検索を行うことができます。
1000次元のベクトルのテーブルに10万レコードを登録して検索性能を比較
インデックスを張らない場合の検索実行時間
# select now();
# select id, name, vec <-> '[...]' from vector2 order by vec <-> '[...]' limit 3;
# select now();
now
-------------------------------
2025-02-10 22:41:46.857061+09
(1 row)
id | name | ?column?
-------+-----------------+--------------------
98408 | name_0000098408 | 11.862095295923496
59794 | name_0000059794 | 11.920021563004825
96991 | name_0000096991 | 11.927945292725399
(3 rows)
now
-------------------------------
2025-02-10 22:41:47.403764+09
(1 row)
約0.6秒かかっています。
インデックスを張った場合の検索実行時間
# create index on vector2 using hnsw(vec vector_l2_ops);
# select now();
# select id, name, vec <-> '[...]' from vector2 order by vec <-> '[...]' limit 3;
# select now();
now
-------------------------------
2025-02-10 23:00:28.030441+09
(1 row)
id | name | ?column?
-------+-----------------+--------------------
43107 | name_0000043107 | 11.891565593957367
93189 | name_0000093189 | 11.940329011764277
29278 | name_0000029278 | 11.961626368144666
(3 rows)
now
-------------------------------
2025-02-10 23:00:28.111582+09
(1 row)
約0.1秒で検索結果を取得できるようになりました。
インデックス作成方法
/* コサイン */
create index on {table名} using hnsw ({column名} vector_cosine_ops);
/* L2 距離 */
create index on {table名} using hnsw ({column名} vector_l2_ops);
/* 内積 */
create index on {table名} using hnsw ({column名} vector_ip_ops);