ByteHouse 提供向量数据的管理与近似度查询功能,通过支持多种常见近似向量查询(Approximate Nearest Neighbor,ANN)算法来提升检索性能,提供对非结构化数据的处理能力。本文介绍了如何使用 SQL 语句在 ByteHouse 中使用 HNSW 或 Faiss Indices 算法库进行向量检索。
ByteHouse 当前支持 HNSW(hnswlib)、Faiss 两个比较流行的检索算法库,支持 HNSW、FLAT、IVF_FLAT、IVF_PQ、IVF_PQ_FS 等多种常用索引。
HNSW 算法库为图类型索引,通过一种最小世界建立图的思路,为每个节点维护 M 个最近邻节点。同时,维护一个分层图结构,越向上越稀疏,查询时从最上层开始,找到最近点以后继续向下一层计算,直到最底层,得到查询向量的 k 个最近邻。
Faiss 是 Facebook 开源的 ANN 算法库,包含了倒排(Inverted File,IVF)、乘积量化(Product Quantization,PQ)、标量量化(Scalar Quantization,SQ)等多种类型的索引,同时多种索引还可以组合使用。ByteHouse 主要使用 Faiss 的 IVF 类索引,同时支持 PQ、PQ_FS(Fsat Scan,快速搜索)等向量压缩方法,以减少索引的内存使用。
ANN 算法库以索引(index)的方式接入,支持通过创建表(create table)或修改表(alter table)添加定义。定义索引后,支持插入数据和使用索引查询。本章节以 HNSW 索引类型为例,帮助您快速上手使用向量检索功能。对于不同索引的详细说明,请参见使用 HNSW 索引、使用 Faiss Indices 索引章节。
CREATE TABLE test_ann ( `id` UInt64, `label` String, `vector` Array(Float32), INDEX v1 vector TYPE HNSW('DIM=960, METRIC=COSINE') ) ENGINE = CnchMergeTree ORDER BY id SETTINGS index_granularity = 1024, -- 缓解读放大问题 index_granularity_bytes = 0 -- 避免生成 adaptive mark
ALTER TABLE test_ann ADD INDEX v1 vector TYPE HNSW('DIM=960, METRIC=COSINE')
参数说明
参数项 | 是否必填 | 配置说明 |
---|---|---|
| 是 | 自定义表名称。 |
``vector | 是 | 将 |
| 是 | 定义索引。本文中基于 |
| 是 | 定义使用的索引类型,并配置对应索引类型相关的内部参数。
索引类型的详细使用指导请参见使用 HNSW 索引、使用 Faiss Indices 索引章节。 |
| 是 | 指定表的存储引擎。配置为 CnchMergeTree。 |
| 是 | 指定表中的数据的排序。 |
| 否 |
ByteHouse 支持配置的全量 settings 参数列表请参见Settings 参数 。 |
支持 ByteHouse 自身的插入(insert)语句,以及 Kafka 等流式导入方式,详情请参见数据导入文档。示例如下:
通过 VALUES 字段导入数据
INSERT INTO test_ann (id, vector) VALUES (1, [1.0, 1.0, 1.0]),(2, [2.0, 2.0, 2.0])
通过 CSV 文件导入数据
INSERT INTO test_ann FORMAT CSV infile '/filename.csv'
本节介绍了如何使用索引查询数据,包含了常规查询和添加 prewhere
条件的混合查询。此外,ByteHouse 也支持添加 where
条件过滤搜索结果,通过相似度阈值筛选符合条件的记录,详情请参见Distance 过滤。
select id, label, dist from test_ann order by cosineDistance(vector, [query_vector]) as dist limit 100 settings enable_new_ann=1
参数项 | 是否必填 | 配置说明 |
---|---|---|
| 是 | 定义向量相似度计算公式。
|
| 是 | 将计算结果重命名为 |
| 是 | 设置返回的记录数。 |
| 是 |
|
ByteHouse 当前也支持带有 prewhere
的混合查询使用方式,例如以下示例使用 prewhere id > 1000
添加预过滤条件,仅处理 id > 1000
的记录。
select id, label, dist from test_ann prewhere id > 1000 order by cosineDistance(vector, [query_vector]) as dist limit 100 settings enable_new_ann=1
使用 HNSW 索引时,可以定义参数 M
和 EF_CONSTRUCTION
,借助这两个参数权衡性能和准确度表现。一般来说 M
的值越大,EF_CONSTRUCTION
的值越大,索引构建时间越长,准确度越高,搜索延迟越高。示例如下:
CREATE TABLE test_ann ( `id` UInt64, `vector` Array(Float32), INDEX v1 vector TYPE HNSW('DIM=960, METRIC=COSINE, M=32, EF_CONSTRUCTION=512') ) ENGINE = MergeTree ORDER BY id SETTINGS index_granularity = 1024
HNSW 索引支持配置的索引参数说明如下。全量索引参数表及使用建议请参见索引参数。
参数项 | 是否必填 | 配置说明 |
---|---|---|
| 否 | 定义了 HNSW 图中每个节点的最大连接数(Max Connections),默认值为 16。M 值较大时(如设置为 32),可以提高搜索速度,但会增加内存占用。M 值较小时(如设置为 4-16),可以降低内存占用,但会降低召回率。 |
| 否 | 定义了索引构建时的探索因子(Exploration Factor),默认值为 200。该值较大(如 512)时,搜索精度更好,但构建时间越长。该值较小(如 100)时,构建速度更快,但索引质量可能会降低。 |
您可使用查询语句检索数据。
此外,ByteHouse 还支持支持添加 prewhere
语句添加预过滤条件,详情请参见混合查询;也支持添加 where
语句用于过滤搜索结果,通过相似度阈值筛选符合条件的记录,详情请参见Distance 过滤。
select id, dist from test_ann order by cosineDistance(vector, [query_vector]) as dist limit 100 settings enable_new_ann=1, hnsw_ef_s=200
参数说明
参数项 | 是否必填 | 配置说明 |
---|---|---|
| 是 |
|
Faiss 不同于 HNSW,构建索引时会进行训练,对 CPU 消耗比较大。使用时,请注意设置以下参数:
vector_index_cache_size
参数配置,默认 200GB。该参数基于最近最少使用策略(Least Recently Used,LRU)实现。vector_index_build_threads
的参数值,默认值为 8,以限制 train index 的并发。Faiss 提供了四种常用的索引类型,并提供了对应的微调参数,用于微调准确度。
FLAT 是 Faiss 中最简单的索引类型,基于暴力搜索实现。它将所有向量存储在内存中,查询时计算查询向量与所有向量的距离,返回最近邻。FLAT 实现简单,无需训练,精确性高,但时间复杂度为 O(n),不适合超大规模数据库。建议在数据量较小、向量维度低、对查询速度要求不高但需要精确结果的情况下使用。
CREATE TABLE tab_flat ( id Int32, vector Array(Float32), INDEX faiss_index vector TYPE FLAT('dim=4') GRANULARITY 1 ) ENGINE = MergeTree ORDER BY id SETTINGS index_granularity = 128
FLAT 索引支持设置的索引参数如下。全量索引参数表及使用建议请参见索引参数。
参数项 | 是否必填 | 配置说明 |
---|---|---|
| 是 | 定义对应向量的维度。 |
| 否 | 定义建立索引时的度量方式。METRIC 参数可以不指定,默认值为 L2,您也可手动配置为 L2 或 COSINE。 |
| 否 | 定义索引粒度,表示每 1 个数据块(mark)构建一次索引。 |
IVF_FLAT 索引结合了倒排文件(IVF)和 FLAT 索引的优点,能够在保持较高检索精度的同时显著提升查询效率,适合中等规模到大规模的低维度向量检索任务(如 4-128 维)。
CREATE TABLE tab_ivf_flat ( id Int32, vector Array(Float32), INDEX faiss_index vector TYPE IVF_FLAT('dim=4') GRANULARITY 1 ) ENGINE = MergeTree ORDER BY id SETTINGS index_granularity = 128
IVF_FLAT 索引支持配置的索引参数说明如下。全量索引参数表及使用建议请参见索引参数。
参数项 | 是否必填 | 配置说明 |
---|---|---|
| 是 | 定义对应向量的维度。 |
| 否 | 定义建立索引时的度量方式。METRIC 参数可以不指定,默认值为 L2,您也可手动配置为 L2 或 COSINE。 |
| 否 | 定义 IVF 类型索引需要的聚类中心数量,数量越多,构建越慢。如果不设置引擎会自动推算,逻辑如下,您可在建表时使用
|
| 否 | 定义索引粒度,表示每 1 个数据块(mark)构建一次索引。 |
IVF_PQ 索引是一种高效的向量压缩和索引方法,结合了倒排文件(IVF)和乘积量化(PQ)的技术,能够在大幅降低内存占用的同时保持较高的检索精度,适用于超大规模数据集(亿级以上向量)。
CREATE TABLE tab_ivf_pq ( id Int32, vector Array(Float32), INDEX faiss_index vector TYPE IVF_PQ('dim=4','m=4','nbit=4') GRANULARITY 1 ) ENGINE = MergeTree ORDER BY id SETTINGS index_granularity = 128
IVF_PQ 索引支持配置的索引参数说明如下。全量索引参数表及使用建议请参见索引参数。
参数项 | 是否必填 | 配置说明 |
---|---|---|
| 是 | 定义对应向量的维度。 |
| 否 | 定义建立索引时的度量方式。METRIC 参数可以不指定,默认值为 L2,您也可手动配置为 L2 或 COSINE。 |
| 是 | 定义乘积量化的子向量数量。常用取值为 64 或者 32,取值范围为 2 的 n 次方,范围介于 [1, std::min(dim, 64)]。 |
| 否 | 定义每个子向量的量化位数。默认值 8,通常无需修改,取值为偶数,通常范围为 [1, 16]。 |
| 是 | 定义 IVF 类型索引需要的聚类中心数量,数量越多,构建越慢, 如果不设置引擎会自动推算。 |
| 否 | 定义索引粒度,表示每 1 个数据块(mark)构建一次索引。 |
IVF_PQ_FS 索引是 IVF_PQ 的增强版,增加了快速搜索(Fast Scan)和 Refine 功能,能够在保持压缩优势的同时提升检索精度,适合需要高精度检索的大规模向量数据。
CREATE TABLE tab_ivf_pq_fs ( id Int32, vector Array(Float32), INDEX faiss_index vector TYPE IVF_PQ_FS('dim=4','m=4') GRANULARITY 1 ) ENGINE = MergeTree ORDER BY id SETTINGS index_granularity = 128
IVF_PQ_FS 索引支持配置的索引参数说明如下。全量索引参数表及使用建议请参见索引参数。
参数项 | 是否必填 | 配置说明 |
---|---|---|
| 是 | 定义对应向量的维度。 |
| 否 | 定义建立索引时的度量方式。METRIC 参数可以不指定,默认值为 L2,您也可手动配置为 L2 或 COSINE。 |
| 是 | 定义乘积量化的子向量数量。常用取值为 64 或者 32,取值范围为 2 的 n 次方,范围介于 [1, std::min(dim, 64)]。 |
| 否 | 定义精排阶段所采用的量化方法,默认使用 RFlat,准确度最高,还可以使用 SQ4、SQ6、SQ8、SQfp16 等标量量化方法。准确度排序为 RFlat>SQfp16>SQ8>SQ6>SQ4,内存资源使用也从多到少。以下为使用 SQ8 的示例:
|
| 否 | 定义 IVF 类型索引需要的聚类中心数量,数量越多,构建越慢, 如果不设置引擎会自动推算。 |
| 否 | 定义索引粒度,表示每 1 个数据块(mark)构建一次索引。 |
您可使用基础查询语句检索数据,也可通过设置 settings 参数,提升准确率。
此外,ByteHouse 还支持支持添加 prewhere
语句添加预过滤条件,详情请参见混合查询;也支持添加 where
语句用于过滤搜索结果,通过相似度阈值筛选符合条件的记录,详情请参见Distance 过滤。
SELECT *, d FROM xxx.yyy ORDER BY L2Distance(vector, [...]) as d limit 3 settings enable_new_ann=1;
参数项 | 是否必填 | 配置说明 |
---|---|---|
| 是 | 定义查询的范围。该示例表示返回表中的所有原始字段,以及向量间距离计算结果
|
| 是 | 定义需要查询的数据库名和表名。 |
| 是 | 定义查询结果的排序方式。
|
| 是 | 设置 settings 参数。
ByteHouse 支持配置的全量 settings 参数列表请参见Settings 参数 。 |
您可以使用 nprobe
和 k_factor_rf
参数为 IVF_FLAT、IVF_PQ 和 IVF_PQ_FS 索引调优查询,以提升查询准确率。ByteHouse 支持配置的全量 settings 参数列表请参见Settings 参数 。
IVF_FLAT 和 IVF_PQ 索引支持设置 nprobe
参数。nprobe
参数指定检索时要访问的 IVF 聚类中心数量。默认是 1,值越大,准确率越好,但性能越差,查询速度越低。取值为 2 的 n 次方,例如 32、64,范围介于 [1, std::min(nlist/2, 查询里的 top n)]。
SELECT *, d FROM xxx.yyy ORDER BY L2Distance(vector, [...]) as d limit 3 settings enable_new_ann=1, nprobe=256;
IVF_PQ_FS 索引支持设置 nprobe
和 k_factor_rf
参数。k_factor_rf
参数可用于控制精排时的候选集扩展倍数,初步检索返回 k
个结果后,将候选集扩大 k_factor_rf
倍(即 k×32
),对扩展后的候选集重新计算精确距离,选出最终的 k
个结果。
SELECT *, d FROM xxx.yyy ORDER BY L2Distance(vector, [...]) as d limit 3 settings enable_new_ann=1, nprobe=256, k_factor_rf=32;
ByteHouse 优化了 where dist < max_score
以及 where dist > min_score
这类单一过滤条件查询,用于过滤搜索结果,通过相似度阈值筛选符合条件的记录。语法示例如下:
select id, dist from test_ann where dist < 0.9 order by cosineDistance(embedding_column, [query_vector]) as dist limit 100
您可以使用以下 settings 参数优化向量检索查询语句。如果您通过 user.xml 文件中配置,则该参数将在全局生效;如果您通过 SQL 语句中配置,则该参数仅对当前语句生效。
参数 | 说明 | 配置方式 | 默认值 | 使用建议 |
---|---|---|---|---|
| 表示索引粒度,即索引中每个标记(mark)对应的行数。设置该参数可以缓解读放大问题,提高查询性能。 | 在建表语句中设置。 | 8192 | 控制每个 Mark 包含的行数,调小可降低读放大,提升向量过滤精度。建议设置为 128。 |
| 表示索引粒度的字节数,当设置为 0 时,会避免生成 adaptive mark,使得索引标记的生成仅基于行数,而不是基于数据的字节数。 | 在建表语句中设置。 | 10485760(约10 MiB) | 禁用 Adaptive Mark,固定 Mark 大小,减少 Mark 定位计算开销。建议设置为 0。 |
| Table level preload 开关。 | 在建表语句中设置。 | 0 | 写入加速。写入后的 part 的向量索引直接进入缓存,消除缓存加载时间。 |
| 是否使用新的 ANN 执行路径。 | 在查询语句中设置。 | 0 | 设置为 1 开启。 |
| 基于 HNSW index 进行 search 时,使用的搜索参数,值越大,准确度越高。 | 在查询语句中设置。 | 10 | Recall 90 以上场景,一般需要设置到 128 以上。 |
| 使用 Faiss IVF 索引(IVF_FLAT、IVF_PQ、IVF_PQ_FS 索引)的搜索参数,表示搜索使用的聚类中心数量。理论上,nprobe 越大,准确度越大,延迟越高。 | 在查询语句中设置。 | 0 (默认为 0 表示未进行设置,index 中默认使用参数为 1) | Recall 90 以上场景,考虑设置到 nlist 的 1/4 以上。 |
| 使用 Faiss 包含 refine 的索引(IVF_PQ_FS 索引)时的搜索参数,k_factor_rf 越大,用于排序的结果越多,准确度越高,延迟越高。 | 在查询语句中设置。 | 0 (同上) | 使用了 refine 的索引,在 recall 较低情况,可以尝试调大,可以先尝试设置为 100,视情况进行微调。 |
| 每个 part build threads 数量。 | 在插入(insert)语句中设置。 | 8 | 单个 part 的 build threads 控制,如果并发导入或者合并并发度较高,建议调小。 |
参数 | 说明 | 适用索引 | 是否必填 | 默认值 |
---|---|---|---|---|
| 定义索引对应向量的维度信息,必须与向量实际的维度一致。 | HNSW、FLAT、IVF_FLAT、IVF_PQ、IVF_PQ_FS | 是 | 960 |
| 定义了建立索引时的度量方式。支持设置为 L2 或 COSINE。 | HNSW、FLAT、IVF_FLAT、IVF_PQ、IVF_PQ_FS | 否 | L2 |
| 定义了 HNSW 图中每个节点的最大连接数(Max Connections)。M 值较大时(如设置为 32),可以提高搜索速度,但会增加内存占用。M 值较小时(如设置为 4-16),可以降低内存占用,但会降低召回率。 | HNSW、IVF_PQ、IVF_PQ_FS | 是 | 16 |
| 定义了索引构建时的探索因子(Exploration Factor)。该值较大(如 512)时,搜索精度更好,但构建时间越长。该值较小(如 100)时,构建速度更快,但索引质量可能会降低。 | HNSW | 是 | 200 |
| 定义索引粒度,表示每 1 个数据块(mark)构建一次索引。 | FLAT、IVF_FLAT、IVF_PQ、IVF_PQ_FS | 是 | |
| 定义每个子向量的量化位数。默认值 8,通常无需修改,取值为偶数,通常范围为 [1, 16]。 | IVF_PQ | 否 | 8 |
| 定义 IVF 类型索引需要的聚类中心数量,数量越多,构建越慢。如果不设置值,引擎会自动推算,逻辑如下,您可在建表时使用 nlist 参数指定每个 part 构建索引时 nlist 的上限。
| IVF_FLAT、IVF_PQ、IVF_PQ_FS | 否 | 无 |
| 定义精排阶段所采用的量化方法,可配置为 RFlat、SQ4、SQ6、SQ8、SQfp16 等标量量化方法。准确度排序为 RFlat>SQfp16>SQ8>SQ6>SQ4,内存资源使用也从多到少。 | IVF_PQ_FS | 否 | RFlat |