矢量值

向量是结构化和非结构化输入数据的数学表示,对现代人工智能(AI)应用和语义搜索能力至关重要。 Db2 现在可以导入矢量数据,并将数据转换为可使用 SQL 语句查询的格式。

注: 支持 VECTOR 数据类型的版本有 Db2®12.1.2 及更高版本中支持 VECTOR 数据类型。

为什么矢量数据很重要?

许多采用机器学习模型和深度学习技术的人工智能应用都会以高维向量嵌入的形式生成向量。 高维向量描述不同物体的数量。 这些应用使用相似性搜索技术来识别数据集中具有相似性的向量,以用于参考向量。 相似性通常用两个向量之间的距离函数来衡量,如欧氏距离或余弦相似性。

许多公司正在采用人工智能和 GenAI 技术,并寻求经济高效、安全和简化的矢量存储解决方案。 为了满足这些需求,应用程序必须具备对一组高维向量嵌入进行高效相似性搜索的能力。 通常,这些应用所需的尺寸数量在数百到数千之间。 这些应用程序数据库中存储的矢量数量通常非常大,因为矢量用于表示每个对象的一小部分。 这些应用程序需要针对单个用户提示运行大量的相似性搜索查询,才能得出答案。 这类查询的预期响应时间从几分之一秒到几毫秒不等。 矢量嵌入通常会保留元数据,这些元数据可纳入相似性搜索查询中。

为什么选择 Db2 来存储和处理矢量数据?

市场上有专门用于矢量存储和高效相似性搜索的数据库。 然而,这些解决方案都有局限性:
  • 它们依赖于外部数据存储库。 在将矢量与原始输入相结合时,用户必须使用多个数据存储库,这就增加了成本、延迟和复杂性。
  • 它们几乎或完全没有能力利用与矢量嵌入相关的元数据来增强查询的其他过滤功能。
  • 它们在其他数据管理领域的能力有限。
许多 Db2 客户的 Db2 数据库中已经有了创建矢量的原始输入,因此他们的矢量存储解决方案得到了极大的简化。

Db2 的查询功能无可匹敌,而新增的向量相似性搜索功能则增强了这些功能。

Db2 多年来,该公司在可扩展性、安全性、可审计性、性能和监控等领域开发出了业界领先的功能。 大多数特定矢量解决方案都无法做到这一点。

有关使用 Db2 管理矢量数据的实际应用示例,请参阅使用案例

VECTOR 数据类型

VECTOR 数据类型目前支持坐标类型 INT8 和 REAL/FLOAT32。 VECTOR 数据类型是一种固定长度类型,其坐标数始终等于维数。 与固定类型 CHAR 和 BINARY 不同,没有填充,所有坐标都必须提供给构造函数。 一个向量只能与另一个具有相同维度和坐标类型的向量兼容。
语法
VECTOR (<dimension> ,<coordinate-type>)
其中:
  • dimension 是一个整数字面量,用于指定向量的维数。 对于行组织表, FLOAT32 的值必须为 1 至 8168, INT8 的值必须为 1 至 32672(SQLSTATE 42611)。 对于列组织的表, FLOAT32 的值必须为 1 至 8148, INT8 的值必须为 1 至 32592(SQLSTATE 42611)。
  • coordinate-type 是 REAL 或 单精度 4 字节浮点数值,或者是 1 字节整数。 FLOAT32 INT8
示例
下面的示例显示了创建包含两列不同矢量数据类型的表 VTABLE 的命令语法:
CREATE TABLE VTABLE (RV VECTOR(100, REAL), -- Coordinates are single-precision (4-byte) floating point
                     IV VECTOR(300, INT8)) -- Coordinates are 1-byte integers
该命令将生成下表:
$ db2 describe table VTABLE

                                Data type                     Column
Column name                     schema    Data type name      Length     Scale Nulls
------------------------------- --------- ------------------- ---------- ----- ------
RV                              SYSIBM    VECTOR(FLOAT32)            100     0 Yes
IV                              SYSIBM    VECTOR(INT8)               300     0 Yes

  1 record(s) selected.

矢量函数及其用途

有几个特定于向量的标量函数,可用于在 Db2:

使用向量进行 UPDATE 和 INSERT 操作

VECTOR 列以二进制格式存储向量。 Db2 在与应用程序交互时使用向量的字符串形式。

例如,新的 VECTOR 函数可将向量的字符串表示转换为二进制形式。 下面的示例显示了使用主机变量和向量字符串形式更新现有向量值的命令语法:

C++
EXEC SQL BEGIN DECLARE SECTION;
  // Generated by db2dclgn
  sqlint32 id;

  struct
  {
    short length;
    char  data[50];
  } f32_3;
EXEC SQL END DECLARE SECTION;

id = 1;
sprintf(f32_3, "[0.123, -0.456, 0.789]");

EXEC SQL UPDATE VECTOR_TB SET F32_3 = VECTOR(:f32_3, 3, FLOAT32) WHERE ID = :id;

矢量的导出、导入和加载操作

导出、导入和载入命令支持 VECTOR 数据类型。 Db2 EXPORTIMPORTLOAD 命令支持 VECTOR 数据类型:
  • EXPORT 和 IMPORT 命令支持以下 VECTOR 数据类型 Db212.1.2 及更高版本中支持 VECTOR 数据类型。 Db2 12.1.3 及更高版本中,LOAD 命令支持 VECTOR 数据类型。
  • EXPORT 命令将向量值写成字符串。 IMPORT 和 LOAD 命令希望输入的矢量数据值是字符串形式。
  • EXPORT 命令输出矢量值的字符串形式,不留不必要的空白。
  • 小尺寸 INT8 VECTOR 类型最多有 6534 个尺寸,而小尺寸 FLOAT32/REAL VECTOR 类型最多有 2041 个尺寸。 对于这些 VECTOR 类型,由 EXPORT 操作生成的向量值的字符串形式不会超过 32672 字节。
  • EXPORT、IMPORT 和 LOAD 命令处理这些小 VECTOR 类型的方式与处理 VARCHAR 类型的方式类似。
  • 如果大型 VECTOR 类型的 INT8 向量的维数超过 6534,或 FLOAT32/REAL 向量的维数超过 2041,那么在 EXPORT 操作中生成的这些向量的字符串形式长度可能会超过 32672 字节。
  • EXPORT、IMPORT 和 LOAD 命令处理大型 VECTOR 类型的方式与处理 CLOB 类型数据的方式类似,使用场景和限制也与 EXPORT、IMPORT 和 LOAD 命令处理实际 CLOB 类型的方式类似。
针对矢量数据运行 EXPORT 命令的规则
在处理大型对象 (LOB) 数据时,EXPORT 语句中可以包含一些选项:
  • 贷款
  • LOBFILE
  • modified by lobsinfile
  • MODIFIED BY lobsinsepfiles
如果在 EXPORT 语句中指定了 LOB 选项,来自大 VECTOR 列的矢量字符串值将被写入单独的 LOB 数据文件,而 LOB 位置指定符(LLS) 将被写入主输出数据文件,以指向矢量字符串值。 如果没有指定 LOB 选项,矢量字符串值将被写入主输出数据文件,如果超出长度,将被截断到最多 32700 字节。 如果数值被截断,不会对特定数据行发出警告。
注意: IMPORT 命令不会将带有截断向量字符串的数据行插入 VECTOR 列 ( SQL0420N )。 在 EXPORT 命令中指定 LOB 选项,除非你有其他方法来避免或减轻截断矢量字符串的问题。
针对矢量数据运行 IMPORT 和 LOAD 命令的规则
  • 在针对具有小 VECTOR 列的表运行 IMPORT 语句 或 LOAD 语句时,矢量字符串值必须位于主输入数据文件中,这些值不得被截断,且大小不得超过 32672 字节。
  • 如果 VECTOR 列较大,且未指定 LOB 选项,则向量字符串值必须位于主输入数据文件中。 LOB 选项示例包括 LOBS FROM 和 MODIFIED BY LOBSINFILE。 同样,矢量字符串值不得截断,大小不得超过 32700 字节。
  • 如果 VECTOR 列较大,且指定了 LOB 选项,则主输入数据文件必须包含指向单独 LOB 数据文件中矢量字符串值的 LLS。 在这种情况下,LOAD 命令支持的矢量字符串值最大可达 1MB (1048576 字节)。 EXPORT 命令不会生成大于 1MB 的矢量字符串值。 对于 LOAD 命令,无论是从远程客户端提交 LOAD 命令,还是使用 CLIENT 参数执行 LOAD 命令,都必须能从服务器访问单独的 LOB 数据文件。 Db2 当从远程客户端提交 LOAD 命令时,以及当 LOAD 命令使用 CLIENT 参数时,都必须能从服务器访问单独的 LOB 数据文件。
  • 从远程客户端运行 LOAD 命令时 Db2 客户端和 Db2 客户端和 Db2 服务器版本都必须是 12.1.3 或更高版本。
    注意: 有时矢量输入数据不是由 EXPORT 命令生成的:它可以由手动或其他工具或应用程序生成。 将矢量字符串数据导入 VECTOR 列类型的规则与导入或加载 EXPORT 命令生成的数据的规则相同。
适用于矢量数据的 EXPORT、IMPORT 和 LOAD 操作的规则
  • 为确保矢量值能成功插入大 VECTOR 列,EXPORT 命令和相应的 IMPORT 或 LOAD 命令都必须使用 LOB 选项或不使用 LOB 选项。 如果不使用 LOB 选项,就有可能出现截断的矢量字符串值。
  • EXPORT、IMPORT 和 LOAD 命令将矢量字符串值视为字符串而非数字。 适用于数值的文件类型修改器不适用于矢量字符串值。 受影响的文件类型修改器包括以下几种:
    • decplusblank.
    • decptx.
    • implieddecimal仅用于导入 导出。
    • striplzeros仅用于出口。
  • 不支持从 VECTOR 列导出矢量值,然后将矢量值导入不同类型的 VECTOR 列。 不同类型的例子包括不同维度或不同坐标类型的向量。
    注:

    EXPORT 和 IMPORT 命令是客户端功能。 从远程客户端运行 EXPORT 和 IMPORT 命令时 Db2 命令时, Db2 客户端和 Db2 服务器实例都必须运行 Db212.1.2 或更高版本,以确保它们都支持 VECTOR 数据类型列。

    LOAD 命令包括客户端和服务器端两个部分。 从远程客户端运行 LOAD 命令时 Db2 时, Db2 客户端和 Db2 服务器实例必须同时运行 Db212.1.3 或更高版本,以确保它们都支持 VECTOR 数据类型列。

矢量限制

以下对象类型和操作不支持 VECTOR 数据类型:
  • 用户自定义类型:
    • 非重复值
    • 阵列。
    • 行类型。
    • 结构类型。
  • 锚定数据类型。
  • 创建昵称。
  • 创建类型映射。

另外:

  • 复制不支持带有 VECTOR 列的表。
  • 向量无法比较。
  • LOAD 和 操作不支持向量。 INGEST
  • db2dart 不支持使用 /DDEL 选项转储 VECTOR 列。
  • 逻辑备份和还原操作不支持 VECTOR 类型。
  • ALTOBJ 存储过程不支持带有 列的表。 VECTOR
  • 现有的列不能更改为 VECTOR。
  • 现有的 VECTOR 列不能更改为不同的数据类型,也不能更改为不同的坐标类型。
  • 不能更改现有的 VECTOR 列尺寸。
  • 唯一允许的 DEFAULT 值是 NULL,因此不能在现有表中添加 NOT NULL 向量列。
  • 在 REFRESH IMMEDIATE 实体化查询表的选择列表中不支持 VECTOR 表达式。
  • 由于在处理向量时没有 "大于 "或 "小于 "的概念,因此 VECTOR 列或带有 VECTOR 结果数据类型的表达式不能以下列方式使用:
    • 作为主键。
    • 作为外键。
    • 作为唯一密钥。
    • 作为 CREATE INDEX 键。
    • 作为 ORDER BY 排序键。
    • 作为 DPF 分配密钥。
    • 作为范围分割键。
    • 作为 MDC 的一把钥匙。
    • 作为 RCT 的关键。
    • 作为 GROUP BY 表达式。
    • IS (NOT) NULL 以外的连接条件下。
    • 作为 SELECT DISTINCT 表达式。
    • 作为 COUNT DISTINCT 表达式。
    • 在 UNION ALL 以外的集合运算符中。

用例

用例 1:从 Db2 表中搜索相似患者记录
您可以使用 Db2 建议的向量支持功能,在关系记录上实现向量相似性搜索。
考虑 Db2 中存储病人记录的数据库表。 表格中的每一行都代表一名患者,包括患者的各种属性和信息,如体型、健康指标、医疗条件和性别。
最近,同桌的一位病人报告说心脏病发作。 医生希望找出与该患者特征相似的其他患者。 这些信息非常重要,因为它能让医生确定哪些病人需要做进一步的医学检查,如血管造影。 不过,需要注意的是,医生并不想让所有病人都去做这些检查。 这是因为这些检查可能很昂贵,而且并非每个病人都有必要做。
为了支持这一使用案例,医院的秘书需要找到与示例病人(称为查询病人 )最相似的其他病人。
图 1。 在 SQL 语句中使用向量
医院的数据科学家使用 SQL 查询将病人记录从 Db2 表检索到 Python 程序中。 它们使用 SQL 语言和自己的视图,以及 Db2 支持的 Python 工具,如 IBM DB 和 Db2 Jupyter Notebook 的 Magic commands 扩展。 通过这些工具,他们可以将所有病人的病历录入 Python 笔记本。
对于每条记录,数据科学家都会将每一列的值与列名连接起来,生成一个句子。 这些句子代表患者的病历,然后将其发送到 RoBerta 等语言模型,为每个句子生成向量嵌入。 这一过程结束后,一个单一的向量就代表了每个病人的特征。 数据科学家通过添加一列 VECTOR 来更改患者表,以存储这些向量。
通过使用 UPDATE 语句,他们将向量存储在患者表的 VECTOR 列中。 矢量存储到 Db2 后,医院秘书就可以使用 VECTOR_DISTANCE 函数编写 SQL 查询,找出与查询病人最相似的五个病人。
用例 2:生成式人工智能/RAG 应用的矢量存储
近年来,大型语言模型(LLM)越来越流行,但也有其局限性。 它们只能在接受过训练的数据上表现出色。 面对新问题时,他们往往会给出错误的答案或胡编乱造。 为了解决这个问题,我们采用了一种名为检索增强生成 (RAG)的方法来增强 LLM 答案。 RAG 利用一个私人知识库,在向 LLM 发出的提示中包括知识库中的相关文件清单。 然后,LLM 会尝试根据这些文件生成答案。 实施 RAG 需要用于存储矢量嵌入的安全数据库和用于存储机密知识内容的安全存储库。 这些内容可以来自 PDF、Word 文档或维基页面。 知识被转换成向量嵌入,并安全地存储在存储库中。
Db2 允许以 blob、clob 和 JSON 等不同列类型存储非结构化内容。 用户可将其私人知识资产存储在 Db2 中。 每个知识资产都可以为其不同部分生成向量嵌入,并使用 VECTOR 列存储在 Db2 中。 预训练或定制训练的 LLM(如 llama 3 )会生成这些嵌入。
要开始搜索,用户需要向应用程序发送一个提示。 应用程序使用与知识资产矢量化相同的 LLM 对提示进行矢量化。 在使用相同的 LLM 对提示信息进行矢量化后,应用程序会生成一个查询矢量,然后利用该矢量在 Db2 中进行矢量相似性搜索。 这种搜索方法会检索出匹配度最高的文件列表,并将其添加到原始提示中。 此外,还包括一条指令,要求 LLM 根据扩充后的文件列表回答用户的查询。
图 2。 使用 Db2
下面是一个使用 Db2 向量支持实现 RAG 应用程序的示例场景:一家软件开发公司希望为其开发人员的文章实施自然语言搜索。 过去,开发人员不得不依赖基于关键字的搜索,而这种搜索有其局限性。 找到合适的关键词是一项挑战,对于初学者来说尤其如此。 搜索结果往往是一长串文件,开发人员必须对其进行筛选,这不仅耗费了大量时间,还包含了不相关的信息。 为了解决这些问题,公司的数据科学团队制定了一项计划,利用人工智能技术让用户能够用自然语言提问。 他们将这些内容以矢量表示的形式存储在 Db2 数据库中,并将原始文章保存为文本文件。
当开发人员提出问题时,应用程序会使用与公司知识资产相同的方法将其转换为矢量。 然后,应用程序在 Db2 数据库中搜索矢量,并检索最相关的文档。 它将这些文件的原文与提示结合起来,然后发送给人工智能模型,指示它仅使用这些文件来回答开发人员的问题。 语言模型努力根据 Db2 中存储的公司私人知识提供答案。