CREATE INDEX USING IVFFLAT¶
向量索引可用于加速对包含向量列的表的 KNN(K-Nearest Neighbors)查询。Matrixone 目前支持具有 l2_distance 度量的 IVFFLAT 向量索引。
语法说明¶
向量索引可用于加速对包含向量列的表的 KNN(K-Nearest Neighbors)查询。Matrixone 目前支持具有 l2_distance 度量的 IVFFLAT 向量索引。
我们可以指定 PROBE_LIMIT 来决定要查询的聚类中心数量。PROBE_LIMIT 默认为 1,即仅扫描 1 个聚类中心。但如果您将其设置为更高的值,它会扫描更多数量的聚类中心和向量,这使得性能可能会下降一点,但准确率会上升。我们可以指定适当的探针数量来平衡查询速度和召回率。PROBE_LIMIT 的理想值为:
如果总行数<1000000:PROBE_LIMIT=总行数/10
如果总行数>1000000:PROBE_LIMIT=sqrt(总行数)
语法结构¶
> CREATE INDEX index_name
USING IVFFLAT
ON tbl_name (col,...)
LISTS=lists
OP_TYPE "vector_l2_ops"
INCLUDE (column_name [, column_name ...])
语法释义¶
index_name:索引名称IVFFLAT:向量索引类型,目前支持 vector_l2_opslists:索引中所需的分区数,必须大于 0OP_TYPE:要使用的距离度量
INCLUDE (column_name, ...) 将非向量列附加到索引中,使覆盖查询可以直接返回或过滤这些列而无需额外回表。INCLUDE 列不参与向量距离计算。IVFFLAT、CAGRA 和 IVFPQ 均支持该子句:
CREATE INDEX idx_ivf USING IVFFLAT ON table_name (embedding)
LISTS 10 OP_TYPE 'vector_l2_ops' INCLUDE (category, price);
CREATE INDEX idx_cagra USING CAGRA ON table_name (embedding)
INCLUDE (category, price);
CREATE INDEX idx_ivfpq USING IVFPQ ON table_name (embedding)
LISTS 4 BITS_PER_CODE 8 INCLUDE (category, price);
INCLUDE 列必须存在于表中,不能是被索引的向量列或主键列,也不能重复。IVFFLAT 最多允许 10 个 INCLUDE 列,并接受其受支持的标量列类型。CAGRA 和 IVFPQ 接受数值类型 INT32、INT64、FLOAT32 和 FLOAT64。HNSW 不支持 INCLUDE。
NOTE:
LISTS 的理想值为:
如果总行数<1000000:lists=总行数/1000
如果总行数>1000000:lists=sqrt(总行数)
建议在数据填充完毕后再创建索引,如果在空表上创建向量索引,则所有向量量都将映射到一个分区,随着时间的推移,数据量不断增长,导致索引变得越来越大,查询性能会下降。
示例¶
drop table if exists t1;
create table t1(coordinate vecf32(2),class char);
-- 有七个点,每个点代表其在 x 和 y 轴上的坐标,并且每个点的 class 被标记为 A 或 B。
insert into t1 values("[2,4]","A"),("[3,5]","A"),("[5,7]","B"),("[7,9]","B"),("[4,6]","A"),("[6,8]","B"),("[8,10]","B");
--创建向量索引
create index idx_t1 using ivfflat on t1(coordinate) lists=1 op_type "vector_l2_ops";
mysql> show create table t1;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
`coordinate` vecf32(2) DEFAULT NULL,
`class` char(1) DEFAULT NULL,
KEY `idx_t1` USING ivfflat (`coordinate`) lists = 1 op_type 'vector_l2_ops'
) |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
mysql> show index from t1;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+-----------------------------------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Index_params | Visible | Expression |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+-----------------------------------------+---------+------------+
| t1 | 1 | idx_t1 | 1 | coordinate | A | 0 | NULL | NULL | YES | ivfflat | | | {"lists":"1","op_type":"vector_l2_ops"} | YES | coordinate |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+-----------------------------------------+---------+------------+
1 row in set (0.01 sec)
--设置扫描的聚类中心数量
SET @PROBE_LIMIT=1;
--现在,我们有一个新点,其坐标为 (4, 4),我们想要使用 KNN 查询来预测这个点的类别。
mysql> select * from t1 order by l2_distance(coordinate,"[4,4]") asc;
+------------+-------+
| coordinate | class |
+------------+-------+
| [3, 5] | A |
| [2, 4] | A |
| [4, 6] | A |
| [5, 7] | B |
| [6, 8] | B |
| [7, 9] | B |
| [8, 10] | B |
+------------+-------+
7 rows in set (0.01 sec)
--根据查询结果可预测这个点的类别为 A
INCLUDE 与 SHOW 元数据¶
以下完整示例创建带 INCLUDE 列的 IVFFLAT 覆盖索引,并展示 INCLUDE 列表的保存位置:
DROP TABLE IF EXISTS vector_include_demo;
CREATE TABLE vector_include_demo (
id INT PRIMARY KEY,
embedding VECF32(3),
category VARCHAR(20),
price INT
);
INSERT INTO vector_include_demo VALUES
(1, '[1, 2, 3]', 'book', 10),
(2, '[2, 3, 4]', 'game', 20);
CREATE INDEX idx_vector_include USING IVFFLAT ON vector_include_demo (embedding)
LISTS 1 OP_TYPE 'vector_l2_ops' INCLUDE (category, price);
SHOW CREATE TABLE vector_include_demo;
SHOW INDEX FROM vector_include_demo;
DROP TABLE vector_include_demo;
IVF 成员资格预下推¶
IVF 向量搜索支持成员资格预下推过滤器,可在向量相似度搜索之前应用关系谓词预过滤行。此优化通过 BY RANK WITH OPTION 子句中的 mode=pre 排名选项激活:
SELECT id, category, score
FROM table_name
WHERE category = 'cat1' AND score > 2.0
ORDER BY l2_distance(embedding, '[0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1]')
LIMIT 3 BY RANK WITH OPTION 'mode=pre';
关系谓词(如 category = 'cat1' AND score > 2.0)构建候选主键过滤器来裁剪向量搜索范围。该过滤对结果透明。
预下推根据源表主键类型使用不同的内部过滤器结构:
整数主键,小 ID 范围:使用密集 cbitmap。
整数主键,宽 ID 跨度(> 2^23):使用紧凑的 CRoaring bitset。
Varchar(非整数)主键:使用 CBloomFilter(近似的、概率性的)。
实验性向量索引变量¶
除 experimental_ivf_index 外,还有两个额外的实验性系统变量控制其他向量索引类型:
experimental_ivfpq_index:控制 IVF-PQ(乘积量化)向量索引。默认值为0(禁用)。experimental_cagra_index:控制 CAGRA(GPU 加速图)向量索引。默认值为0(禁用)。
这些变量可在会话或全局范围内设置:
-- 会话范围
SET experimental_ivfpq_index = 1;
SET experimental_cagra_index = 1;
-- 全局范围
SET GLOBAL experimental_ivfpq_index = 1;
SET GLOBAL experimental_cagra_index = 1;
-- 查询当前值
SELECT @@experimental_ivfpq_index, @@experimental_cagra_index;
SHOW VARIABLES LIKE 'experimental_ivfpq_index';
SHOW VARIABLES LIKE 'experimental_cagra_index';
限制¶
一次只支持在一个向量列上建立向量索引,如需在多个向量列上建立向量索引,可多次执行创建语句。