跳转到主要内容
Laion-400M 数据集包含 4 亿张带有英文图像说明的图片。如今,Laion 还提供了规模更大的数据集,不过其使用方式与本数据集类似。 该数据集包含图片 URL、图片及其图像说明各自的嵌入向量、图片与图像说明之间的相似度评分,以及元数据,例如图片的宽度/高度、许可证和 NSFW 标记。我们可以使用该数据集来演示 ClickHouse 中的近似最近邻搜索

数据准备

原始数据中的嵌入向量和元数据分别存储在不同的文件中。数据准备这一步会下载数据、合并这些文件, 将其转换为 CSV 并导入 ClickHouse。为此,你可以使用下面的 download.sh 脚本:
脚本 process.py 的定义如下:
要启动数据准备管道,请运行:
该数据集被拆分为 410 个文件,每个文件包含约 100 万行。如果你想处理更小的数据子集,只需调整限制即可,例如 seq 0 9 | ... (上面的 python 脚本非常慢 (每个文件约需 2–10 分钟) ,占用大量内存 (每个文件 41 GB) ,生成的 csv 文件也很大 (每个 10 GB) ,因此请务必谨慎。如果你有足够的 RAM,可以增大 -P1 的值以提高并行度。如果这样仍然太慢,可以考虑采用更好的摄取流程——例如先将 .npy 文件转换为 Parquet,然后再用 ClickHouse 完成其余处理。)

创建表

如需先创建一个不带索引的表,请运行:
将 CSV 文件导入 ClickHouse:
请注意,id 列仅作示意,脚本会为其填入非唯一值。 要执行穷举的近似向量搜索,请运行:
target 是一个包含 512 个元素的数组,也是一个客户端参数。 文末会介绍一种便捷的方式来获取这类数组。 现在,我们可以先把一张随机 LEGO 套装图片的嵌入向量作为 target 结果

使用向量相似度索引执行近似向量相似度搜索

现在,我们来在该表上定义两个向量相似度索引。
索引创建和搜索的参数及性能注意事项,请参见文档。 上述索引定义的是一个 HNSW 索引,使用 “余弦距离” 作为距离度量,其中参数 “hnsw_max_connections_per_layer” 设为 64,参数 “hnsw_candidate_list_size_for_construction” 设为 256。 该索引使用半精度脑浮点数 (bfloat16) 进行量化,以优化内存占用。 要构建并物化该索引,请运行以下语句:
构建并保存索引可能需要几分钟,甚至几小时,具体取决于行数和 HNSW 索引参数。 要执行向量搜索,只需再次运行相同的查询:
结果
由于通过向量索引检索最近邻,查询延迟显著降低。 使用向量相似度索引进行向量相似度搜索时,返回的结果可能与穷举搜索的结果略有差异。 通过谨慎选择 HNSW 参数并评估索引质量,HNSW 索引有望实现接近 1 的召回率 (即达到与穷举搜索相同的准确性) 。

使用 UDF 创建嵌入向量

通常需要为新图像或新的图像说明创建嵌入向量,并在数据中搜索相似的图像/图像说明对。我们可以使用 UDF 直接在客户端内创建 target 向量,而无需离开客户端。务必使用同一个模型来生成数据以及用于搜索的新嵌入向量。以下脚本使用 ViT-B/32 模型,底层数据集也是基于该模型构建的。

文本嵌入向量

首先,将以下 Python 脚本保存到 ClickHouse 数据路径中的 user_scripts/ 目录,并将其设为可执行文件 (chmod +x encode_text.py) 。 encode_text.py:
然后在您的 ClickHouse 服务器配置文件中,由 <user_defined_executable_functions_config>/path/to/*_function.xml</user_defined_executable_functions_config> 指定的位置创建 encode_text_function.xml
现在只需使用:
第一次运行会比较慢,因为需要加载模型,但之后再次运行就会很快。然后,我们可以将输出复制到 SET param_target=... 中,这样就能轻松编写查询。或者,也可以直接将 encode_text() 函数作为 cosineDistance 函数的参数使用:
请注意,encode_text() UDF 本身可能需要几秒钟才能完成计算并生成嵌入向量。

图像嵌入向量

图像嵌入向量也可以用类似的方法创建。我们提供了一个 Python 脚本,可为本地文件中的图像生成嵌入向量。 encode_image.py
encode_image_function.xml
下载一张用于搜索的示例图片:
然后执行以下查询,为上述图片生成 embedding:
完整的查询如下:
最后修改于 2026年6月12日