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);