资源规划
使用BES向量数据库前,用户需要优先结合业务需求和所存数据,评估集群所需的资源容量。评估方式如下:
资源估算
CPU资源
CPU资源决定了向量数据库查询的QPS能力,以基于标准embedding的768维数据为例,单节点100万条数据的情况下,数据节点的CPU数量与查询QPS能力关系如下:
CPU核数 = 预估QPS / 80
上述核数估计方式是经验公式,实际生产中一般需要通过压测方式评估最佳CPU核数选择。
内存资源
BES的数据节点默认会预留一半内存给 JVM(JVM最大占用30G内存),向量模块默认分配剩余内存的 50% 为向量数据构建索引。
向量索引的最大内存占用比例可以通过`circuit_breaker_limit`参数调节,默认设置为 50%。调节方式如下:
PUT /_cluster/settings
{
"persistent" : {
"bpack.knn.memory.circuit_breaker.limit" : "70%"
}
}
快速评估内存
我们对于单节点容纳常用维度向量的能力进行了预算;提供不同节点规格,单节点支持常用维度向量的最大数据数量级。
如果用户使用的向量维度,算法以及向量模块分配内存比例与我们计算条件相匹配,可以通过下表进行快速集群规模计算。
基于标准embedding的768维数据,以HNSW算法存储,circuit_breaker_limit
参数为 50% 情况下,单节点支持最大向量数据量级如下表所示:
BES数据节点内存规格 | JVM堆内存 | 向量索引占用的最大内存 | 单节点支持的最大向量数据量 |
---|---|---|---|
32G | 16G | 8G | 2,000,000 |
64G | 30G | 17G | 4,000,000 |
128G | 30G | 49G | 14,000,000 |
基于标准embedding的384维数据,以HNSW算法存储,circuit_breaker_limit
参数为 50% 情况下,单节点支持最大向量数据量级如下表所示:
BES数据节点内存规格 | JVM堆内存 | 向量索引占用的最大内存 | 单节点支持的最大向量数据量 |
---|---|---|---|
32G | 16G | 8G | 4,000,000 |
64G | 30G | 17G | 9,000,000 |
128G | 30G | 49G | 26,000,000 |
上述单节点支持的最大向量数据量,均在不存在副本情况计算所得;如果存在k个副本,则单节点支持的最大向量数据量需要除以(1+k)
例如基于标准embedding的768维数据,以HNSW算法存储,
circuit_breaker_limit
参数为 50% 为情况下,如果存在3个副本,32G规格节点单节点最大支持向量的数据量为500000
内存详细估算方式
如果用户使用的向量维度、算法或者内存分配比例参数与上述预算条件不同,可以通过以下方式计算所需的集群规模。
以下为一种通过估算集群的内存用量来计算集群规模的方法。需要考虑的因素包括算法的选择、给向量索引分配内存比例、向量维度和数量以及副本数。
HNSW 内存预估公式
HNSW 所需的存放向量索引内存估算公式为:
(1.1 * (4 * dims + 8 * M) * num of vectors ) bytes
注:其中M值表示构造HNSW索引期间为每个新元素创建的双向链接数。M值越高,消耗内存、存储空间以及构造时间越多但是准确率更高。
建议根据min(向量维度 * 1.5, 32)取值,一般12-48可以满足大多数场景的需求。
假设用户有100万个维度为 768 的向量,且 M 设置为 32,内存需求可以估计如下:
1.1 * (4 * 768 + 8 * 32) * 1,000,000 ≈ 3.409 GB
IVF 内存预估公式
IVF 所需的存放向量索引内存估算公式为:
1.1 * (((4 * dims) * num of vectors) + (4 * nlist * dims)) bytes.
假设用户有100万个维度为256的向量,且 nlist 设置为128,内存需求可以估计如下:
1.1 * (((4 * 256) * 1,000,000) + (4 * 128 * 256)) ≈ 1.126 GB
节点规模试算
以HNSW算法为例,1亿条768维向量(默认 M 为32),副本数为1,节点规格选择8核64G,则使用节点数为
向量占用的内存总量 (1.1 * (4 * dims + 8 * M) * num of vectors ) bytes = (1.1 * (4 * 768 + 8 * 32) * 10kw)= 366080000000 byte ≈ 340.939 GB
考虑到有1个副本,所需要提供给向量的总内存为 340.939 GB * (1 + 1) = 681.878 GB
使用默认circuit_breaker_limit = 50%,则规格为64G的节点,单节点可以提供给向量数据的最大内存为(64G-30G)* 50% = 17G
因此需要节点数为 681.878 GB / 17G = 40.011台 ≈ 41 台
如果使用16核128G节点,并且调整 circuit_breaker_limit
为70%,则使用节点数为
向量占用的内存总量 (1.1 * (4 * dims + 8 * M) * num of vectors ) bytes = (1.1 * (4 * 768 + 8 * 32) * 10kw)= 366080000000 byte ≈ 340.939 GB
考虑到有1个副本,所需要提供给向量的总内存为 340.939 GB * (1 + 1) = 681.878 GB
使用默认circuit_breaker_limit = 50%,则规格为128G的节点,单节点可以提供给向量数据的最大内存为(128G-30G)* 70% = 68.6G
因此需要节点数为 681.878 GB / 68.6G = 42.617台 ≈ 9.940 台 ≈ 10 台
磁盘资源
数据节点所需存储容量计算方式如下:
存储容量 = 源数据大小 * (1 + 副本数量) * (1 + 数据膨胀) * (1 + 内部其他开销) * (1 + 预留空间)
源数据大小 = 标量数据量 + 向量数据量
标量数据量 = 原始标量数据的字节数
向量数据量 ≈ (4 * dims) * num of vectors * 4
- 副本数量: 推荐的副本数量为1
- 数据膨胀: 一般情况下源数据会膨胀10%-50%,用于 ES 存储索引、列存数据等 (_all参数等未计算)
- 内部其他开销: 需要预留20%,用于 segment 合并、ES Translog 等内部操作
- 安全阈值: 在上述基础上,通常至少再额外预留30%的安全阈值
因此最终的所需容量计算公式为:
存储容量 ≈ 源数据大小 * (1 + 副本数量) * 1.7
具体原理详见 https://cloud.baidu.com/doc/BES/s/Vke3oar2l
以8核64G和16核128G的BES节点为例,数据量和选购磁盘的关系如下:
标量数据 | 向量数据量 (基于标准embedding的768维数据) | 副本分片数 | 节点规格 | 建议节点数 | 所需磁盘总大小 | 建议选购单机规格 |
---|---|---|---|---|---|---|
1000G | 10,000,000 | 1 | 8核64G | 5 | 3520G | 8核64G + 700G磁盘 |
10,000G | 100,000,000 | 1 | 8核64G | 41 | 35200G | 8核64G + 900G磁盘 |
1000G | 10,000,000 | 1 | 16核128G | 2 | 3520G | 16核128G + 1.8T磁盘 |
10,000G | 100,000,000 | 1 | 16核128G | 10 | 35200G | 16核128G + 3.5T磁盘 |