Skip to content

向量索引使用

liguoqiang edited this page Jan 4, 2024 · 2 revisions

建表

CREATE TABLE `t_vec` (
  `id` int(10) NOT NULL ,
  `vec` varchar(1024) NOT NULL , //向量,使用逗号分割字符串表示,0.16,0.32,0.002。。。
  `__weight` float NULL , // 每次请求返回距离
  `id2` int(10) NOT NULL ,
 PRIMARY KEY (`id`,`id2`) COMMENT '{"index_state":"IS_PUBLIC", "hint_status":"IHS_NORMAL"}',
 VECTOR KEY  `idx` (`vec`) COMMENT '{"vector_description":"HNSW16", "dimension":16, "nprobe":5, "metric_type":"METRIC_L2"}'
) ENGINE=Rocksdb DEFAULT CHARSET=gbk AVG_ROW_LENGTH=200 COMMENT='{"resource_tag":"", "replica_num":3, "region_split_lines":524288, "namespace":"TEST"}'
PARTITION BY RANGE(id2)   // 目前partition字段必须包含在主键里
(
    PARTITION p1 VALUES [1, 2),
    PARTITION p2 VALUES [2, 3),
    PARTITION p3 VALUES [3, 4)
);
// 对于分区表可以无损增加分区
ALTER TABLE t_vec ADD PARTITION p4 VALUES [4, 5);
建表可选特殊字段表示距离,每次运行后返回的数据会实时填这两个字段
`__weight` float  NULL,               //返回距离,类型不能错,不能写double
'{"vector_description":"HNSW16", "dimension":16, "nprobe":5,"efsearch":16,"efconstruction":40, "metric_type":"METRIC_L2"}'
  • VECTOR KEY表示向量索引,内部使用faiss库:https://github.com/facebookresearch/faiss/
  • dimension:向量维度,必填,文心一言是384维,chatgpt是1536维
  • vector_description:可以描述索引类型,目前只支持:FLAT,HNSWx(x建议16)三种索引,不填默认是HNSW16
  • metric_type:距离表示,默认METRIC_L2(https://github.com/facebookresearch/faiss/wiki/MetricType-and-distances)
    • METRIC_L2(默认值):Faiss报告平方欧几里得(L2)距离,避免了平方根。这仍然是单调的欧几里得距离,但如果需要精确的距离,则需要对结果进行额外的平方根运算。该度量不受数据旋转(正交矩阵变换)的影响。__weight范围0~1
    • METRIC_INNER_PRODUCT:这通常用于推荐系统中最大内积搜索。查询向量的范数不会影响结果排名(当然数据库向量的范数很重要)。除非向量被归一化(位于单位超球面上;请参见下文余弦相似性),否则它本身并不是余弦相似性。
    • 余弦相似度:依然选METRIC_INNER_PRODUCT,向量需要做归一化,vector_description加上L2norm,前缀,比如HNSW16索引,改成L2norm,HNSW16;erniebot embedding后已经是归一化,不需要加L2norm。__weight范围-1~+1
  • nprobe:IVF前缀索引时,表示搜索的质点数,默认5
  • efsearch:HNSW查询期间要访问的最近邻居的数量,默认是16
  • efconstruction:HNSW构建索引期间要访问的最近邻居的数量,默认是40

查询

向量比较暂时复用match against语法,match(vector_field) against ('0.1,0.2,0.3...' in vector mode) 常规查询:查询top 10的向量

  • select * from table where match(vector_field) against ('0.1,0.2,0.3...' in vector mode) order by __weight asc limit 10; // METRIC_L2用asc,METRIC_INNER_PRODUCT用desc 组合其他条件
  • where match(vector_field) against ('0.1,0.2,0.3...' in vector mode) and tag = 3 支持partition
  • select * from table partition(p0) where match(vector_field) against ('0.1,0.2,0.3...' in vector mode) order by __weight asc limit 10; // METRIC_L2用asc,METRIC_INNER_PRODUCT用desc

插入

语法与普通表相同,向量使用逗号分割字符串表示,分割出的数量必须与dimension相等 insert into table (id, name, vec) values (1, 'abc', '0.163,0.182,...');

  • FLAT:不需要train,直接按行插入
  • IVFxPQy(任意IVF+其他):引入FLAT层,1000行批量插入,新增超过20000(阈值),则train+add index
  • HNSWx:支持批量add,引入FLAT层,1000行批量插入

删除

语法与普通表相同:delete from table where id=3;

更新

语法与普通表相同:

  • update table set name='xxx' where id=3; 更新非向量字段,不改变向量索引
  • update table set vector_field='0.3,0.4,...' where id=3; 更新向量字段,会转化未删除索引/插入索引两个步骤