向量数据类型 (Vector)
向量指的是一组浮点数序列,例如 [0.3, 0.5, -0.1, ...]
。针对 AI 应用中大量使用到的嵌入向量 (vector embedding) 数据,TiDB 专门提供了向量数据类型,以便高效地存储和访问这些数据。
目前支持的向量数据类型包括:
VECTOR
:存储一组单精度浮点数 (Float) 向量,向量维度可以是任意的。VECTOR(D)
:存储一组单精度浮点数 (Float) 向量,向量维度固定为D
。
与使用 JSON
类型相比,使用向量类型具有以下优势:
- 支持向量索引。可以通过构建向量搜索索引加速查询。
- 可指定维度。指定一个固定维度后,不符合维度的数据将被阻止写入到表中。
- 存储格式更优。向量数据类型针对向量数据进行了特别优化,在空间利用和性能效率上都优于
JSON
类型。
语法
可以使用以下格式的字符串来表示一个数据类型为向量的值:
'[<float>, <float>, ...]'
示例:
CREATE TABLE vector_table (
id INT PRIMARY KEY,
embedding VECTOR(3)
);
INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]');
INSERT INTO vector_table VALUES (2, NULL);
插入不符合语法的字符串作为向量数据时,TiDB 会报错:
[tidb]> INSERT INTO vector_table VALUES (3, '[5, ]');
ERROR 1105 (HY000): Invalid vector text: [5, ]
下面的示例中 embedding
向量列的维度在建表时已经定义为 3
,因此当插入其他维度的向量数据时,TiDB 会报错:
[tidb]> INSERT INTO vector_table VALUES (4, '[0.3, 0.5]');
ERROR 1105 (HY000): vector has 2 dimensions, does not fit VECTOR(3)
关于向量数据类型支持的所有函数和操作符,可参阅向量函数与操作符。
关于向量搜索索引的更多信息,可参阅向量搜索索引。
混合存储不同维度的向量
省略 VECTOR
类型中的维度参数后,就可以在同一列中存储不同维度的向量:
CREATE TABLE vector_table (
id INT PRIMARY KEY,
embedding VECTOR
);
INSERT INTO vector_table VALUES (1, '[0.3, 0.5, -0.1]'); -- 插入一个 3 维向量
INSERT INTO vector_table VALUES (2, '[0.3, 0.5]'); -- 插入一个 2 维向量
需要注意的是,存储了不同维度向量的列不支持构建向量搜索索引,因为只有维度相同的向量之间才能计算向量距离。
比较
向量数据支持比较运算符,例如 =
、!=
、<
、>
、<=
和 >=
等。关于向量数据类型支持的所有函数和操作符,可参阅向量函数与操作符。
比较向量数据类型时,TiDB 会以向量中的各个元素为单位进行依次比较,如:
[1] < [12]
[1,2,3] < [1,2,5]
[1,2,3] = [1,2,3]
[2,2,3] > [1,2,3]
当两个向量的维度不同时,TiDB 采用字典序 (Lexicographical Order) 进行比较,具体规则如下:
- 两个向量中的各个元素逐一进行数值比较。
- 当遇到第一个不同的元素时,它们之间的数值比较结果即为两个向量之间的比较结果。
- 如果一个向量是另一个向量的前缀,那么维度小的向量小于维度大的向量。例如,
[1,2,3] < [1,2,3,0]
。 - 长度相同且各个元素相同的两个向量相等。
- 空向量小于任何非空向量。例如,
[] < [1]
。 - 两个空向量相等。
在进行向量比较时,请使用显式转换将向量数据从字符串转换为向量类型,以避免 TiDB 直接基于字符串进行比较:
-- 因为给出的数据实际上是字符串,因此 TiDB 会按字符串进行比较
[tidb]> SELECT '[12.0]' < '[4.0]';
+--------------------+
| '[12.0]' < '[4.0]' |
+--------------------+
| 1 |
+--------------------+
1 row in set (0.01 sec)
-- 显式转换为向量类型,从而按照向量的比较规则进行正确的比较
[tidb]> SELECT VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]');
+--------------------------------------------------+
| VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]') |
+--------------------------------------------------+
| 0 |
+--------------------------------------------------+
1 row in set (0.01 sec)
运算
向量数据类型支持算术运算 +
和 -
,对应的是两个向量以元素为单位进行的加法和减法。不支持对不同维度向量进行算术运算,执行这类运算会遇到报错。
以下是一些示例:
[tidb]> SELECT VEC_FROM_TEXT('[4]') + VEC_FROM_TEXT('[5]');
+---------------------------------------------+
| VEC_FROM_TEXT('[4]') + VEC_FROM_TEXT('[5]') |
+---------------------------------------------+
| [9] |
+---------------------------------------------+
1 row in set (0.01 sec)
[tidb]> SELECT VEC_FROM_TEXT('[2,3,4]') - VEC_FROM_TEXT('[1,2,3]');
+-----------------------------------------------------+
| VEC_FROM_TEXT('[2,3,4]') - VEC_FROM_TEXT('[1,2,3]') |
+-----------------------------------------------------+
| [1,1,1] |
+-----------------------------------------------------+
1 row in set (0.01 sec)
[tidb]> SELECT VEC_FROM_TEXT('[4]') + VEC_FROM_TEXT('[1,2,3]');
ERROR 1105 (HY000): vectors have different dimensions: 1 and 3
类型转换 (Cast)
向量与字符串之间的转换
可以使用以下函数在向量和字符串之间进行转换:
CAST(... AS VECTOR)
:将字符串类型转换为向量类型CAST(... AS CHAR)
:将向量类型转换为字符串类型VEC_FROM_TEXT
:将字符串类型转换为向量类型VEC_AS_TEXT
:将向量类型转换为字符串类型
出于易用性考虑,如果你使用的函数只支持向量数据类型(例如,向量相关距离函数),那么你也可以直接传入符合格式要求的字符串数据,TiDB 会进行隐式转换:
-- VEC_DIMS 只接受向量类型,因此你可以直接传入字符串类型,TiDB 会隐式转换为向量类型:
[tidb]> SELECT VEC_DIMS('[0.3, 0.5, -0.1]');
+------------------------------+
| VEC_DIMS('[0.3, 0.5, -0.1]') |
+------------------------------+
| 3 |
+------------------------------+
1 row in set (0.01 sec)
-- 也可以使用 VEC_FROM_TEXT 显式地将字符串转换为向量类型后传递给 VEC_DIMS 函数:
[tidb]> SELECT VEC_DIMS(VEC_FROM_TEXT('[0.3, 0.5, -0.1]'));
+---------------------------------------------+
| VEC_DIMS(VEC_FROM_TEXT('[0.3, 0.5, -0.1]')) |
+---------------------------------------------+
| 3 |
+---------------------------------------------+
1 row in set (0.01 sec)
-- 也可以使用 CAST(... AS VECTOR) 进行显式转换:
[tidb]> SELECT VEC_DIMS(CAST('[0.3, 0.5, -0.1]' AS VECTOR));
+----------------------------------------------+
| VEC_DIMS(CAST('[0.3, 0.5, -0.1]' AS VECTOR)) |
+----------------------------------------------+
| 3 |
+----------------------------------------------+
1 row in set (0.01 sec)
当你使用的运算符或函数接受多种数据类型时,TiDB 不会进行隐式转换,请先显式地将字符串类型转换为向量类型后,再传递给这些运算符或函数。例如,进行比较运算前,需要显式地将字符串转换为向量类型,否则 TiDB 将会按照字符串类型进行比较,而非按照向量类型进行比较:
-- 传入的类型是字符串,因此 TiDB 会按字符串进行比较:
[tidb]> SELECT '[12.0]' < '[4.0]';
+--------------------+
| '[12.0]' < '[4.0]' |
+--------------------+
| 1 |
+--------------------+
1 row in set (0.01 sec)
-- 转换为向量类型,以便使用向量类型的比较规则:
[tidb]> SELECT VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]');
+--------------------------------------------------+
| VEC_FROM_TEXT('[12.0]') < VEC_FROM_TEXT('[4.0]') |
+--------------------------------------------------+
| 0 |
+--------------------------------------------------+
1 row in set (0.01 sec)
向量也可以显式地转换为字符串。以使用 VEC_AS_TEXT()
函数为例:
-- 字符串首先被隐式地转换成向量,然后被显式地转为字符串,因而返回了一个规范化的字符串格式:
[tidb]> SELECT VEC_AS_TEXT('[0.3, 0.5, -0.1]');
+--------------------------------------+
| VEC_AS_TEXT('[0.3, 0.5, -0.1]') |
+--------------------------------------+
| [0.3,0.5,-0.1] |
+--------------------------------------+
1 row in set (0.01 sec)
如需了解其他转换函数,请参阅向量函数和操作符。
向量与其他数据类型之间的转换
目前 TiDB 无法直接在向量和其他数据类型(如 JSON
)之间进行转换,但你可以在执行的 SQL 语句中使用字符串作为中间类型进行转换。
需要注意的是,对于存储在表中的向量数据类型列,无法通过 ALTER TABLE ... MODIFY COLUMN ...
转换为其他数据类型。
使用限制
有关向量类型的限制,请参阅向量搜索限制以及向量搜索索引的使用限制。
MySQL 兼容性
向量数据类型只在 TiDB 中支持,MySQL 不支持。