向量数据类型 (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 不支持。

另请参阅

文档内容是否有帮助?