Skip to content

Commit 34934a0

Browse files
authored
Update MiniOB VectorDB Document (#606)
update miniob-vectordb.md
1 parent 6389d2a commit 34934a0

File tree

1 file changed

+57
-140
lines changed

1 file changed

+57
-140
lines changed

docs/docs/game/miniob-vectordb.md

Lines changed: 57 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: MiniOB 向量数据库
33
---
4+
45
# MiniOB 向量数据库
56

67
## 向量搜索
@@ -10,6 +11,7 @@ title: MiniOB 向量数据库
1011
### 向量(Vector)是什么
1112

1213
向量是一种表示多维特征的数据结构。每个向量由一组数值组成,这些数值通常对应于某种特定的特征或属性。例如,在图像处理中,一个向量可以表示图像的颜色、纹理等特征。为了更有效地管理非结构化数据,常见的做法是将其转换为向量表示,并存储在向量数据库中,这种转换过程通常被称为 Embedding。通过将文本、图像或其他非结构化数据映射到高维向量空间,我们可以捕捉数据的语义特征和潜在关系。单词、短语或整个文档以及图像、音频和其他类型的数据都可以表示成向量,例如,我们可以将下面的文本表示成向量:
14+
1315
```
1416
"West Highland White Terrier": [0.0296700,0.0231020,0.0166550,0.0642470,-0.0110980, ... ,0.0253750]
1517
```
@@ -30,188 +32,103 @@ title: MiniOB 向量数据库
3032

3133
注意:在实现向量数据库相关题目时,不限制向量检索算法的实现方式,可以基于开源的第三方库实现,也可以自行实现。
3234

33-
### 题目一:向量类型基础功能
34-
* 向量类型
35-
* 语法:`vector(size)`,其中,size 表示向量的维度(必须指定)
36-
* 最大支持维度为 16000(在基础功能中只需要支持最大 1000 维向量即可)
37-
* 向量类型中的浮点数最多保留两位小数,并且去掉多余的0
38-
* 向量类型中每个元素都是数值类型(包括int 和 float 类型)。
39-
* 支持创建包含向量类型的表:
40-
```sql
41-
CREATE TABLE items (id int, embedding vector(3));
42-
```
43-
* 支持插入向量类型的记录(注意:这里需要支持将字符串类型的值转换为向量类型存储):
44-
```sql
45-
INSERT INTO items VALUES (1, '[1,2,3]');
46-
```
47-
* 支持向量类型的算术运算(加法(+),减法(-),乘法(*),比较运算):
35+
### MiniOB 向量类型
36+
37+
VECTOR 是一种结构,最多可以容纳指定数量的条目 N,定义如下:
38+
4839
```sql
49-
select embedding + '[1.5,2.3,3.3]', embedding - '[1,2,3]', '[1,2,3]' - embedding from items where embedding > '[0,0,0]';
40+
VECTOR(N)
5041
```
51-
其中,算术运算为逐个元素运算,如 `[1,2,3] + [1,1,1] = [2,3,4], [1,2,3] - [1,1,1]=[0,1,2], [1,2] * [1,3] = [1,6]`;比较运算为逐个元素的字典序比较。即两个向量比较时,从左到右逐个数值进行比较,如果某个位置的数值不同,则根据该位置的数值大小比较结果作为向量的比较结果,举例:`[1,2,3]<[1,2,4], [2,1,2]>[1,2,2]`
52-
53-
* 支持距离表达式计算:
54-
* l2_distance
55-
* 语法:l2_distance(vector A, vector B)
56-
* 计算公式:$[ D = \sqrt{\sum_{i=1}^{n} (A_{i} - B_{i})^2} ]$
5742

58-
* cosine_distance:
59-
* 语法:cosine_distance(vector A, vector B)
60-
* 计算公式:$[ D = 1 - \frac{\mathbf{A} \cdot \mathbf{B}}{|\mathbf{A}| |\mathbf{B}|} = 1 - \frac{\sum_{i=1}^{n} A_i B_i}{\sqrt{\sum_{i=1}^{n} A_i^2} \sqrt{\sum_{i=1}^{n} B_i^2}} ]$
43+
每个条目是一个 4 字节(单精度)浮点数值。
6144

62-
* inner_product:
63-
* 语法:inner_product(vector A, vector B)
64-
* 计算公式:$[ D = \mathbf{A} \cdot \mathbf{B} = a_1 b_1 + a_2 b_2 + ... + a_n b_n = \sum_{i=1}^{n} a_i b_i ]$
45+
默认长度为 2048;最大条目数为 16383。要声明一个使用默认长度的 VECTOR 列,应定义为 `VECTOR` 而不带括号;尝试以 `VECTOR()`(空括号)方式定义列将引发语法错误。
6546

66-
* 距离表达式的计算精度为保留2位小数。
47+
VECTOR 不能与任何其他类型进行比较。它可以与其他 VECTOR 进行相等性比较,但不支持其他比较操作。
6748

68-
### 题目二:向量类型扩展
49+
- 支持创建包含向量类型的表:
6950

70-
支持使用列表(如:`[1,2,3]`)来表示向量:
7151
```sql
72-
select embedding + [1.5,2.3,3.3], embedding - '[1,2,3]',[1,2,3] - embedding from items where embedding > [0,0,0];
52+
CREATE TABLE items (id int, embedding vector(3));
7353
```
7454

75-
### 题目三:高维向量
55+
- 支持插入向量类型的记录(注意:这里需要支持 `STRING_TO_VECTOR` 函数将字符串类型的值转换为向量类型存储):
7656

77-
* 需要支持最大 16000 维向量的存储和检索。
78-
* 不需要考虑在高维向量上建立向量索引。
79-
* 高维向量的存储可以参考 TEXT 类型的实现。
57+
```sql
58+
INSERT INTO items VALUES (1, STRING_TO_VECTOR('[1,2,3]'));
59+
```
8060

81-
### 题目四:向量索引(一)
82-
在本次赛题中,需要实现 IVF-Flat 向量索引,下面简单介绍 IVF-Flat 向量索引的工作原理及相关语法。
83-
IVF-Flat 是一种常见的高效近似最近邻(Approximate Nearest Neighbor,ANN)搜索算法,尤其适用于大型、高维向量数据集。它通过一种称为倒排文件索引(Inverted File Index)的机制来加速向量检索。IVF-Flat 的主要思想是将所有的高维向量分为多个簇,然后在每个簇内进行精确的向量搜索。这种方法通过减少需要比较的向量数量,大大提高了搜索速度。
61+
- 支持用于处理 VECTOR 值的 SQL 函数。
8462

85-
具体来说,IVF-Flat 包括两个主要步骤:
63+
| 名称 | 描述 |
64+
| ------------------ | ------------------------------------------------ |
65+
| DISTANCE() | 根据指定的方法计算两个向量之间的距离 |
66+
| STRING_TO_VECTOR() | 获取由符合格式的字符串表示的 VECTOR 列的二进制值 |
67+
| VECTOR_TO_STRING() | 获取 VECTOR 列的字符串表示,给定其二进制值 |
8668

87-
* 向量分组(簇划分):将所有向量通过聚类算法(如 K-Means)分为多个簇。每个簇都有一个中心点(质心),所有向量都分配到离它最近的质心。下面的左图表示将所有向量分为若干个簇。
69+
**DISTANCE(vector, vector, string)**
8870

89-
* 倒排文件索引:建立一个倒排文件索引,将向量的索引存储在对应簇的列表中。然后,通过这个索引来快速锁定需要比较的向量集合。下面的右图表示向量索引检索的过程。
71+
计算两个向量之间的距离,根据指定的计算方法。它接受以下参数:
9072

91-
![ivfflat](images/ivfflat.png)
92-
以图像搜索为例的 IVF-Flat 向量索引工作流程如下:
93-
1. 首先使用 K-Means 算法将所有图像的特征向量分成 1000 个簇。每个簇表示一部分相似的图片。例如,簇 1 可能包含大部分是风景图像的向量,簇 2 可能包含大部分是人物图像的向量,以此类推。对于每个簇,向量索引都维护一个倒排文件索引,存储属于这个簇的所有图像的索引。
94-
比如,簇 1 对应的倒排文件索引可能包括 [image_23, image_45, image_78...],这些是属于簇 1 的图像的索引。
95-
2. 查询过程:用户指定一张新图像进行搜索。首先,将这张图片通过同样的特征提取模型转换成一个高维向量。然后,通过计算这个向量与1000个质心的距离,找到离它最近的几个质心(假设是前5个)。在这几个质心对应的簇中,你进一步进行精确的向量搜索,找到最相似的图像。
73+
- 一个 VECTOR 数据类型的列。
74+
- 一个 VECTOR 数据类型的输入查询。
75+
- 一个字符串,指定了距离度量方式。支持的值有 COSINE、DOT 和 EUCLIDEAN。由于该参数是字符串,因此必须加引号。
9676

77+
- l2_distance
9778

98-
向量索引语法:
99-
```sql
100-
CREATE VECTOR INDEX vector_idx
101-
ON items (embedding)
102-
WITH (distance=l2_distance, type=ivfflat, lists=245, probes=5);
103-
```
104-
其中 embedding 是向量索引列,必须指定是 vector 类型,`VECTOR INDEX` 必须搭配使用。vector_idx 是向量索引名,`WITH` 后面为创建向量索引的基本参数, 括号内部是一个表达式列表 其中的 `distance` 表示距离算法,必须是 `inner_product``l2_distance``cosine_distance` 其中的一种,`type` 为索引算法类型,当前只支持 ivfflat。`lists` 为 ivfflat 索引构建期间创建的簇的数量。`probes` 为一个向量检索时参数,用于确定查询期间要查询的簇的数量。注意:所有的关键字都是大小写不敏感的。
79+
- 语法:l2_distance(vector A, vector B)
80+
- 计算公式:$[ D = \sqrt{\sum_{i=1}^{n} (A_{i} - B_{i})^2} ]$
10581

106-
邻近向量检索语法:
107-
```sql
108-
select column_name1,column_name2, ... from table_name order by vector_distance_func(vector_column_name, '[float0,float1,……]') limit K;
109-
```
110-
* vector_distance_func是向量距离表达式:
111-
* l2_distance
112-
* inner_product
113-
* cosine_distance
114-
* 要求order by子句表达式必须是一个向量距离表达式,且目前只支持向量列与常量向量
115-
* 要求limit子句必须是一个整数常量表达式
82+
- cosine_distance:
11683

117-
本题目中只需要支持:
84+
- 语法:cosine_distance(vector A, vector B)
85+
- 计算公式:$[ D = 1 - \frac{\mathbf{A} \cdot \mathbf{B}}{|\mathbf{A}| |\mathbf{B}|} = 1 - \frac{\sum_{i=1}^{n} A_i B_i}{\sqrt{\sum_{i=1}^{n} A_i^2} \sqrt{\sum_{i=1}^{n} B_i^2}} ]$
11886

119-
1. 创建 Ivf-Flat 向量索引(本题目不考察 ANN 查询)。
120-
2. 当查询为邻近向量检索且命中向量索引时,需要将 order by + limit 的查询计划改写为通过向量索引进行检索的查询计划。
87+
- inner_product:
88+
- 语法:inner_product(vector A, vector B)
89+
- 计算公式:$[ D = \mathbf{A} \cdot \mathbf{B} = a_1 b_1 + a_2 b_2 + ... + a_n b_n = \sum_{i=1}^{n} a_i b_i ]$
12190

122-
向量索引检索的查询计划示例如下:
123-
```sql
124-
EXPLAIN SELECT C1, L2_DISTANCE(C1, '[1,2,3]') FROM TEST ORDER BY L2_DISTANCE('[1,2,3]', C1) LIMIT 3;
91+
**VECTOR_DISTANCE 是此函数的同义词。**
12592

126-
Query Plan
127-
OPERATOR(NAME)
128-
PROJECT
129-
└─VECTOR_INDEX_SCAN(V_I ON TEST)
130-
```
131-
132-
### 题目五:向量索引题目(二)
133-
134-
* 需要在没有索引的场景下,支持向量检索功能(即精确检索)。
135-
* 需要支持完整的向量检索功能(包括向量索引构建,向量索引查询)。
136-
137-
向量检索示例:
13893
```sql
139-
SELECT * FROM TAB_VEC ORDER BY L2_DISTANCE(B, '[1,2,3]') LIMIT 1;
94+
SELECT DISTANCE(STRING_TO_VECTOR("[1.01231, 2.0123123, 3.0123123, 4.01231231]"), STRING_TO_VECTOR("[1, 2, 3, 4]"), "COSINE");
14095
```
14196

142-
### 题目六:ann-benchmarks
143-
144-
[ann-benchmarks](https://github.com/erikbern/ann-benchmarks) 是一个用于评估近似最近邻(Approximate Nearest Neighbor, ANN)搜索算法性能的工具和框架。我们使用 ann-benchmarks 来测试 MiniOB 向量搜索相关功能。
145-
本地运行支持 MiniOB 的 ann-benchmarks 测试的步骤如下:
97+
---
14698

147-
赛题测试程序中运行的 ann-benchmarks 只针对 `fashion-mnist-784-euclidean` 数据集进行测试,`--runs` 参数为1,测试使用的 python 脚本与 [ann-benchmarks](https://github.com/oceanbase/ann-benchmarks/tree/miniob) 完全相同,指定向量索引参数 `probes = 5, lists = 245`
148-
测试程序不对性能做过多的限制,满足如下要求即为通过:
99+
**STRING_TO_VECTOR(string)**
149100

150-
1. 要求在 10 分钟内完成 ann-benchmarks 的整个运行(即包括:插入数据,创建索引,ANN 查询,不包括下载数据集的时间)。
151-
2. 要求 ANN 查询的每秒查询数(QPS)达到 100 qps
152-
3. 要求 ANN 查询的召回率(recall)达到 0.90
153-
4. 考虑向量索引的内存占用,要求 ann-benchmarks 运行过程中 miniob 的最大内存占用不超过 1 GB。
101+
将向量的字符串表示转换为二进制形式。字符串的预期格式是一个或多个逗号分隔的浮点数值列表,用方括号([ ])包围。值可以用十进制或科学记数法表示。由于该参数是字符串,因此必须加引号。
154102

155-
注意: 需要对 MiniOB 代码进行修改,以支持运行 ann-benchmarks 测试(如MiniOB 现有的 MySQL 通讯协议需要兼容 ann-benchmarks 所使用的 pymysql)。
103+
**TO_VECTOR() 是此函数的同义词。**
156104

157-
#### 在 MiniOB 上运行 ann-benchmark
105+
VECTOR_TO_STRING() 是此函数的逆操作:
158106

159-
* 下载 ann-benchmarks 代码
160-
```
161-
git clone https://github.com/oceanbase/ann-benchmarks.git -b miniob
162-
```
163-
* 安装所需 python 依赖
164-
```
165-
cd ann-benchmarks/
166-
pip install -r requirements.txt
167-
```
168-
* 以 mysql 通讯协议且监听 unix socket 的方式启动 miniob.
169-
```bash
170-
# 示例命令
171-
/root/miniob/build_release/bin/observer -s /tmp/miniob.sock -P mysql
172-
```
173-
* 运行 ann-benchmark.
174-
注意:需要将 `algorithms/miniob/config.yml` 中的 `arg_groups: [{unix_socket: "/tmp/miniob.sock"}]` 修改为 miniob 实际使用的 unix socket 文件地址
175-
```bash
176-
# 示例命令
177-
python3 run.py --dataset fashion-mnist-784-euclidean --docker-tag ann-benchmarks-miniob --local --timeout 100 --runs 1
178-
```
179-
* 生成运行结果.
180-
```bash
181-
# 示例命令
182-
python3 plot.py --dataset fashion-mnist-784-euclidean
183-
# 示例输出如下,其中每行结果倒数第一个值为该算法对应的QPS,每行结果倒数第二个值为该算法对应的召回率。
184-
writing output to results/fashion-mnist-784-euclidean.png
185-
Computing knn metrics
186-
0: MiniOBVector() 0.968 167.476
187-
Computing knn metrics
188-
1: BruteForceBLAS() 1.000 355.359
107+
```sql
108+
SELECT VECTOR_TO_STRING(STRING_TO_VECTOR("[1.05, -17.8, 32]"));
189109
```
190110

191-
### MiniOB 向量数据库语法示例
111+
此类值中的所有空白字符(数字后、方括号前或后,或两者的任意组合)在使用时都会被修剪。
192112

193-
```sql
194-
-- 建表语句
195-
CREATE TABLE TEST (ID INT, C1 VECTOR(3), C2 VECTOR(3), C3 VECTOR(4));
113+
---
196114

197-
-- 插入语句
198-
INSERT INTO TEST VALUES(1, '[1,1,1]', '[1,2,3]', '[1,2,3,4]');
115+
**VECTOR_TO_STRING(vector)**
199116

200-
-- 查询语句
201-
SELECT C1, C2, L2_DISTANCE(C1, C2), L2_DISTANCE('[1,1,1]', '[1,2,3]'), COSINE_DISTANCE('[1,1,1]', C2) FROM TEST;
202-
SELECT C1, C2, C1 + '[1.5,2.3,3.3]', '[3.3,55.55,66.66]' - C2, C2 * C1 FROM TEST;
117+
给定一个 VECTOR 列值的二进制表示,此函数返回其字符串表示,该格式与 STRING_TO_VECTOR() 函数的参数格式相同。
203118

204-
-- 创建索引
205-
CREATE VECTOR INDEX V_I ON TAB_VEC(B) WITH(TYPE=IVFFLAT, DISTANCE=L2_DISTANCE, LISTS=3, PROBES=3);
119+
**FROM_VECTOR() 被接受为此函数的同义词。**
206120

207-
-- ANN 查询
208-
SELECT * FROM TAB_VEC ORDER BY L2_DISTANCE(B, '[1,2,3]') LIMIT 1;
209-
```
121+
无法解析为向量值的参数会引发错误。
122+
123+
此函数的输出最大大小为 262128(16 \* 16383)字节。
210124

211125
## 参考资料
126+
212127
[向量数据库](https://en.wikipedia.org/wiki/Vector_database)
213128

214-
[pgvector](https://github.com/pgvector/pgvector)
129+
[MySQL 向量类型介绍](https://dev.mysql.com/doc/refman/9.4/en/vector.html)
130+
131+
[MySQL 向量函数介绍](https://dev.mysql.com/doc/refman/9.4/en/vector-functions.html)
215132

216133
[ivfflat 原理介绍](https://www.timescale.com/blog/nearest-neighbor-indexes-what-are-ivfflat-indexes-in-pgvector-and-how-do-they-work/)
217134

0 commit comments

Comments
 (0)