返回

文章详情

在线点查询的数据湖索引

Hacker News2026年8月1日 15:41

像Spotify这样的公司需要大量数据在低延迟下可供在线服务访问,并且越来越多的AI代理代表用户进行操作。在线服务——如使用或显示用户收听历史的门户和个性化功能——需要以交互速度查找和分页每个用户的数据。AI代理回答诸如“我去年夏天听了什么?”这样的问题时,需要快速检索用户的数据,以便能够对其进行推理——过滤、聚合,甚至在本地运行SQL——以为大型语言模型的提示建立上下文。这两种模式共享相同的基础原理:通过键进行快速点查询,对数据集进行访问,而这些数据集往往大得过于庞大,以至于无法经济地保留在类似Bigtable或DynamoDB的键值(KV)存储中。在Spotify,千兆字节数据驻留在Bigtable中用于在线使用案例——而在GCS数据湖中则存储着外层字节。湖泊的底层存储速度很快,并且变得越来越快——GCS每个请求的响应时间为30-100毫秒,而S3 Express One Zone和GCS快速存储现在提供单数字毫秒延迟。瓶颈越来越多地不在存储层本身,而是在其上的查询引擎:诸如Trino和BigQuery之类的分布式SQL引擎在作业调度和查询规划上增加了几秒的开销,即使是对单行查找。它们被设计用于分析吞吐量,而不是交互点查询。随机访问Parquet(RAP)弥补了这一差距。一个外部索引将键直接映射到文件位置,精确的范围读取则获取所需的字节。RAP在已经被机器学习管道、笔记本、实验平台和批量分析共享的Parquet文件上运行——存储一次,支付一次,而不是在专门的服务系统中维护单独的副本。分布式SQL引擎如何在堆中找到针用户询问AI代理他们去年夏天听了什么。仅收听历史数据就跨越了数十亿的用户和每天数千个大文件,而夏天大约有90天。如果每天有1,000个文件,那么就是90,000个单独的Parquet文件。在任何合理的时间或计算预算内,即便是对每个文件读取一点点,都是不切实际的。减少候选集有一些标准方法。在每个每日分区内,文件还可以按键进行进一步分区——这是加速连接的常用技术,当键设置正确时,也有助于加速点查找。仅从文件名,引擎就知道给定的用户ID是否可能在该文件中。每天有1,000个桶,候选集从90,000减少到90。用户ID列上的布隆过滤器可以在不开启文件的情况下筛除文件——缓存于元数据存储中,它们将90个候选集缩小到用户实际活跃的12天。我们仍需读取这12个文件。每个文件都很大,在其中找到一个用户的数据需要一系列依赖读取:获取页脚,解析行组元数据,扫描键列以定位匹配的行,然后使用列和页索引在每个值列中找到相应的页。这对于每个文件的每一列来说都是多个往返依赖取用的过程——每个往返请求都与所有其他并发查询争夺I/O操作。按键分区和布隆过滤器有助于选择文件,但并没有解决文件内部的问题。RAP方法依赖读取链是根本的瓶颈,这在每个存储层上都是如此。每个环节都消耗延迟(在下一个可以开始之前的一个往返)和带宽(读取字节只是为了发现下一个读取的位置)。在云存储上,每个I/O环节的延迟成本为数十毫秒;在本地SSD上为微秒;在内存中为纳秒。绝对数据会变化,但结构是相同的:每一步都依赖于上一步骤的结果。压缩这一链条——用单个预计算查找代替依赖读取——节省了延迟和带宽,无论存储层次如何。我们在云对象存储上展示了这一方法,因为每个往返的成本使得好处最为显著,但该原理是通用的。RAP不是扫描,而是查找。一个外部索引将每个键直接映射到其数据的位置的每个文件和行号。给定一个键,读者查找该索引,用缓存的文件元数据解析出行号到页位置,并发出范围读取以精确获取所需的页。索引查找是O(1),缓存的页映射是低延迟操作,数据检索是少量精确的范围读取。重要的是,这些读取可以并行发出——没有依赖加载链。外部索引RAP可以在任何现有的Parquet文件上运行,无需特殊准备。索引构建器读取将要检索的列的页脚和页面位置,扫描键列以构建键到位置的映射,并将其写出。随着新数据的到来,每个管道运行生成相应的索引条目。

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡