矢量数据库

矢量数据库以矢量的形式来存储和管理数据,这些矢量是数据点的数值阵列。

使用矢量可以进行复杂的查询和分析,因为可以使用高级技术(如矢量相似度搜索、量化和聚类分析)来比较和分析矢量。 传统数据库不太适合处理在数据分析中越来越常见的高维数据。 但是,矢量数据库可以通过将高维数据(如文本、图像和音频)表示为矢量来处理这些数据。 矢量数据库适用于机器学习、自然语言处理、图像识别等任务,其目标是识别大型数据集中的模式或相似度。

本文提供有关矢量数据库的一些背景,并在概念上介绍了如何在 Microsoft Fabric 的实时智能中将 Eventhouse 用作矢量数据库。 有关实际示例,请参阅教程:使用 Eventhouse 作为矢量数据库

关键概念

矢量数据库使用了以下关键概念:

向量相似性

矢量相似度是衡量两个或更多矢量的不同程度(或相似程度)的度量值。 矢量相似度搜索是一种用于在数据集中查找相似矢量的技术。 使用距离指标(例如欧几里得距离余弦相似度)来比较矢量。 两个矢量越接近,它们就越相似。

嵌入

嵌入是一种以矢量格式表示数据的常见方法,适用于矢量数据库。 嵌入是一段数据(例如字词、文本文档或图像)的数学表示形式,旨在捕获其语义含义。 嵌入是使用算法创建的,这些算法可以分析数据并生成一组表示其关键特征的数值。 例如,字词的嵌入可能表示其含义、上下文以及与其他字词的关系。 创建嵌入的过程非常简单。 虽然可以使用标准 python 包(例如 spaCy、sent2vec、Gensim)创建嵌入,但大型语言模型 (LLM) 可以生成最高质量的嵌入,以便进行语义文本搜索。 例如,你可以将文本发送到 Azure OpenAI 中的嵌入模型,并生成可存储用于分析的矢量表示形式。 有关详细信息,请参阅了解 Azure OpenAI 服务中的嵌入

常规工作流

如何嵌入、存储、查询作为矢量存储的文本的示意图。

使用矢量数据库的常规工作流如下所示:

  1. 嵌入数据:使用嵌入模型,将数据转换为矢量格式。 例如,可以使用 OpenAI 模型来嵌入文本数据。
  2. 存储矢量:将嵌入的矢量存储在矢量数据库中。 可将嵌入的数据发送到 Eventhouse 以便存储和管理矢量。
  3. 嵌入查询:使用用于嵌入存储数据的相同嵌入模型,将查询数据转换为矢量格式。
  4. 查询矢量:使用矢量相似度搜索,查找数据库中与查询相似的条目。

Eventhouse 作为矢量数据库

矢量相似度搜索的核心是存储、索引、查询矢量数据的能力。 Eventhouse 提供了一种用于处理和分析大量数据(特别是在需要实时分析和探索的场景中)的解决方案,成为存储和搜索矢量的理想选择。

以下组件让 Eventhouse 能够用作矢量数据库:

  • 动态数据类型,可以存储数组和属性包等非结构化数据。 因此,建议使用数据类型来存储矢量值。 通过将与原始对象相关的元数据存储为表中的单独列,可以进一步增强矢量值。
  • 编码类型 Vector16,用于以 16 位精度来存储浮点数的矢量,使用 Bfloat16 而不是默认的 64 位。 强烈建议使用此编码来存储 ML 矢量嵌入,因为它可将存储需求减少到原来的 1/4,并将矢量处理函数 series_dot_product()series_cosine_similarity() 函数加快几个数量级。
  • series_cosine_similarity 函数,它可以对存储在 Eventhouse 中的矢量执行矢量相似度搜索。

针对缩放进行优化

有关优化矢量相似性搜索的详细信息,请阅读博客

若要最大程度地优化性能和产生的搜索时间,请执行以下步骤:

  1. 将嵌入列的编码设置为 Vector16,该编码是矢量系数的 16 位编码(而不是默认的 64 位)。
  2. 将嵌入矢量表存储在每个处理器至少有一个分片的所有群集节点上,可通过以下步骤完成此操作:
    1. 通过更改分片策略ShardEngineMaxRowCount 来限制每个分片的嵌入矢量数。 分片策略平衡每个节点具有多个盘区的所有节点上的数据,以便搜索可以使用所有可用的处理器。
    2. 更改合并策略RowCountUpperBoundForMerge。 需要合并策略才能在引入后禁止合并盘区。

示例优化步骤

在以下示例中,为存储 1M 矢量定义了静态矢量表。 嵌入策略定义为 Vector16,分片和合并策略被设置为针对矢量相似性搜索优化表。 因此,假设群集有 20 个节点,每个节点有 16 个处理器。 表的分片应最多包含 1000000/(20*16)=3125 行。

  1. 以下 KQL 命令逐个运行,以创建空表并设置所需的策略和编码:

    .create table embedding_vectors(vector_id:long, vector:dynamic)                                  //  This is a sample selection of columns, you can add more columns
    
    .alter column embedding_vectors.vector policy encoding type = 'Vector16'                         // Store the coefficients in 16 bits instead of 64 bits accelerating calculation of dot product, suppress redundant indexing
    
    .alter-merge table embedding_vectors policy sharding '{ "ShardEngineMaxRowCount" : 3125 }'       // Balanced data on all nodes and, multiple extents per node so the search can use all processors 
    
    .alter-merge table embedding_vectors policy merge '{ "RowCountUpperBoundForMerge" : 3125 }'      // Suppress merging extents after ingestion
    
  2. 将数据引入到在上一步创建和定义的表。

下一步