Hacker News 中文摘要

RSS订阅

NVMe SSD加速索引I/O -- Faster Index I/O with NVMe SSDs

文章摘要

Marginalia搜索索引进行了部分重写,采用新数据结构以更好地利用现代硬件,特别是NVMe SSD的读取性能。索引规模从3.5亿文档增至8亿,查询性能优化在100-250ms内提升搜索结果质量。未来计划增加多语言索引,进一步扩大索引规模。广告检测系统已完成编码,待更多数据后发布详细说明。

文章总结

标题:利用NVMe SSD加速索引I/O

主要内容:

Marginalia搜索引擎的索引部分经过重新设计,采用了新的数据结构,以更好地利用现代硬件。本文详细介绍了这一新设计,并探讨了NVMe SSD在读取大小方面的一些意外性能特征。

索引已经相当庞大,但由于查询性能的优化,有时感觉比实际小。每个查询的时间预算为100-250毫秒,设计在此时间内更快地找到和排序结果,从而产生更好的搜索结果。此外,索引文档的限制和过滤条件有所放宽,索引从3.5亿个文档增长到8亿个文档。下一步任务是为更多语言编制索引,这可能会进一步增加索引规模。

索引设计的高层次概述可以类比为C++代码中的数据结构,如倒排索引和位置列表。这些数据结构被视为不可变的,因此可以忽略传统数据库管理系统中的并发修改问题。

查询过程包括:1) 查询中每个词的文档列表相交;2) 检索包含所有词的文档的位置;3) 使用文档ID及其相关位置对文档进行排序;4) 返回最佳N个结果。

倒排索引结构被实现为内存映射的B树。尽管有论文指出使用MMAP在数据库管理系统中可能存在问题,但为了逐步解决问题,这一设计被暂时忽略。

在Linux中,文件读取有两种模式:缓冲读取和直接读取。缓冲读取通过系统页面缓存,而直接读取则不使用系统缓存,直接将数据复制到缓冲区。对于数据库开发,直接读取通常更有利,因为它避免了缓存未命中时的数据复制,并且具有更一致的延迟。

B树的重新设计首先尝试使用直接读取模式重新实现现有的B树结构,但效果不佳。随后,采用了确定性块跳表结构,这种结构在排序列表交集任务中表现出色,并且更容易实现。

性能评估使用了两个基准测试,查询为“to be or not to be”。测试结果显示,较大的块大小(如128 KB)在查找和执行测试中表现最佳,而更大的块大小则导致性能下降。

NVMe SSD在现代企业环境中表现出色,几乎无论读取多少数据,所需时间大致相同。通过调整块大小,索引的读取性能显著提升。128 KB的块大小在查找和执行测试中表现最佳,而更大的块大小则导致性能下降。

为了进一步优化性能,采用了iouring技术来加速位置数据的读取。尽管iouring在随机指针遍历中表现不佳,但在其他磁盘读取任务中表现优异。通过将位置数据检索分配到有限的线程中,减少了I/O争用,提高了整体吞吐量。

数据局部性优化通过重新排列位置数据的位置,减少了读取次数。在缓冲读取模式下,使用POSIX_FADV_RANDOM可以更好地合并读取请求,提高性能。

结论是,要进一步优化性能,需要在IOPS方面进行更多优化。当前的瓶颈在于位置数据的IOPS。通过更好的压缩算法或近似位置匹配技术,可能减少位置检索的次数。充分利用NVMe SSD的性能需要进行大量基准测试,并重新审视旧的假设。

这些更改已合并到主分支并在生产环境中部署,经过一些小的初期问题后,表现良好。生产部署中使用了128 KB的块大小,但64 KB到256 KB之间的值表现相似。新索引设计旨在充分利用NVMe SSD的性能,但也可以在多种硬件上运行,并且大部分是可配置的。

进一步阅读: - 从外部存储器读取 - Ruslan Savchenko - 在单个ThreadRipper工作站上实现11M IOPS和66 GiB/s IO - Tanel Poder - 你真的想在数据库管理系统中使用MMAP吗? - Crotty, Andrew and Leis, Viktor and Pavlo, Andrew.

评论总结

评论1(评分:无,作者:marginalia_nu): 作者强烈推荐读者阅读其文末链接的论文和文章,认为这些内容非常出色。 - 关键引用: - "I urge you to read the papers and articles I linked at the end if any of this is your jam."(“如果你对这些内容感兴趣,我强烈建议你阅读我文末链接的论文和文章。”) - "They are incredible bangers all of them."(“它们都非常出色。”)

评论2(评分:无,作者:dataflow): 作者提出了一个关于模型结构的问题,质疑为什么使用list而不是mapset来存储数据。 - 关键引用: - "Beginner(?) question: why is the model..."(“初学者问题:为什么模型是...”) - "(or using set<> in lieu of list<> as appropriate)?"(“或者适当使用set代替list?”)