实现背景
最近邻域搜索(ANN)是指在 n 维空间中找到与给定点距离最小的点的问题。如果数据要逐条对比,性能和内存都有很大的消耗,所以添加了 annoy_index 索引,利用 ann 索引来加速计算。相关PR:https://github.com/ClickHouse/ClickHouse/pull/40818
使用限制
- ClickHouse 的 ANN 索引还有很多局限性
- 目前是个实验性功能需要开始 setting 才能使用(
SET allow_experimental_annoy_index = 1
) - 由于算法存在内存安全问题,目前已在 ARM 上禁用
- 如果 where 和 order by 同时使用时,没有效率提升,所以必须和 limit 子句一起使用
- 只有当 limit 的值小于 max_limit_for_ann_queries(默认:100W)时,才会使用 ANN 索引加速,否则会很消耗内存。
- 目前是个实验性功能需要开始 setting 才能使用(
特殊函数支持及 ANN 索引使用方法
-
ClickHouse 为此增加几个特殊的函数来支持查询,如 L2Normalize、L2Norm 等。示例如下:
SELECT L2Distance((1, 2), (2, 3)); ┌─L2Distance((1, 2), (2, 3))─┐ │ 1.4142135623730951 │ └────────────────────────────┘ SELECT L2Norm((1, 2)); ┌───L2Norm((1, 2))─┐ │ 2.23606797749979 │ └──────────────────┘
-
ANN 索引使用示例如下,更多示例详见:示例
CREATE TABLE 02354_annoy ( id Int32, embedding Array(Float32), INDEX annoy_index embedding TYPE annoy(100) GRANULARITY 1 ) ENGINE = MergeTree ORDER BY id SETTINGS index_granularity=5; INSERT INTO 02354_annoy VALUES (1, [0.0, 0.0, 10.0]), (2, [0.0, 0.0, 10.5]), (3, [0.0, 0.0, 9.5]), (4, [0.0, 0.0, 9.7]), (5, [0.0, 0.0, 10.2]), (6, [10.0, 0.0, 0.0]), (7, [9.5, 0.0, 0.0]), (8, [9.7, 0.0, 0.0]), (9, [10.2, 0.0, 0.0]), (10, [10.5, 0.0, 0.0]), (11, [0.0, 10.0, 0.0]), (12, [0.0, 9.5, 0.0]), (13, [0.0, 9.7, 0.0]), (14, [0.0, 10.2, 0.0]), (15, [0.0, 10.5, 0.0]); SELECT * FROM 02354_annoy WHERE L2Distance(embedding, [0.0, 0.0, 10.0]) < 1.0 LIMIT 5; # 1 [0,0,10] # 2 [0,0,10.5] # 3 [0,0,9.5] # 4 [0,0,9.7] # 5 [0,0,10.2]