通过 best_compression 提升搜索性能

虽然 best_compression 通常被视为 Elastic Observability 和 Elastic Security 用例的存储节省功能,但本篇博客将展示其作为搜索性能调优工具的有效性。

测试 Elastic 领先、开箱即用的功能。深入了解我们的示例笔记本,开始免费云服务试用,或立即在您的本地计算机上试用 Elastic

在为高并发工作负载调优 Elasticsearch 时,标准方法是最大限度地增加 RAM,将工作文档集保存在内存中,以实现低搜索延迟。因此,best_compression 很少被考虑用于搜索工作负载,因为它主要被视为 Elastic Observability 和 Elastic Security 用例中优先考虑存储效率的节省存储措施。

在本博客中,我们证明当数据集大小显著超出操作系统页面缓存时,best_compression通过减少 I/O 瓶颈来提升搜索性能和资源效率。

设置

我们的用例是一个运行在 Elastic Cloud CPU 优化实例上的高并发搜索应用程序。

  • 数据量:约 5 亿份文档
  • 基础架构:6 个 Elastic Cloud(Elasticsearch 服务)实例(每个实例:1.76 TB 存储 | 60 GB 内存 | 31.9 个 vCPU)
  • 内存与存储比率:约 5% 的总数据集可存储在 RAM 中

症状:高延迟

我们观察到,当当前请求数在 19:00 左右激增时,搜索延迟显著恶化。如图 1 和图 2 所示,尽管每个 Elasticsearch 实例的流量峰值约为每分钟 400 个请求,但平均查询服务时间仍恶化至超过 60 毫秒。

在完成初始连接处理后,CPU 使用率保持相对较低,表明计算并非瓶颈。

查询量与页面错误之间出现了强相关性。随着请求增加,我们观察到页面错误比例上升,峰值约为每分钟 40 万次。这表明活跃数据集无法完全放入页面缓存。

同时,JVM 堆使用率也显示正常且平稳。这排除了垃圾回收问题,并确认瓶颈在于 I/O。

诊断:I/O 瓶颈

系统存在 I/O 瓶颈。Elasticsearch 依赖操作系统页面缓存从内存提供索引数据。当索引过大而无法放入缓存时,查询会触发开销很大的磁盘读取。虽然典型的解决方案是水平扩展(添加节点/RAM),但我们希望先充分利用现有资源的效率改进。

解决方案

默认情况下,Elasticsearch 对其索引段使用 LZ4 压缩,在速度和大小之间取得平衡。我们假设,改用 best_compression (使用 zstd)会减少索引的大小。更小的占用空间使得更大比例的索引能够放入页面缓存,以微不足道的 CPU 增加(用于解压缩)换取磁盘 I/O 的减少。

为了启用 best_compression,我们使用索引设置 index.codec: best_compression 重新索引了数据。或者,也可以通过关闭索引、将索引编解码器重置为 best_compression,然后进行段合并,也可实现相同的结果。

结果

结果证实了我们的假设:存储效率的提高直接转化为搜索性能的大幅提升,而 CPU 利用率并未相应增加。

应用 best_compression 后,索引大小减少了约 25%。虽然低于在重复日志数据中观察到的减少幅度,但这 25% 的减少实际上将我们的页面缓存容量提升了相同的比例。

在下一次负载测试期间(从 17:00 开始),流量甚至更高,每个 Elasticsearch 节点的请求峰值达到每分钟 500 次。

尽管负载更高,但 CPU 利用率仍低于上一次运行。先前测试中较高的使用率可能是由于过多的页面错误处理和磁盘 I/O 管理开销所致。

至关重要的是,页面错误显著下降。即使在更高的吞吐量下,错误次数也稳定维持在每分钟低于 20 万次,而基准测试中的错误次数则超过 30 万次。

尽管页面错误结果仍然不太理想,但查询服务时间却减少了约 50%,即使在负载更重的情况下也保持在 30 毫秒以下。

对于搜索用例中数据量超过可用物理内存的情况,best_compression 是一个强大的性能调优工具。

应对缓存未命中的常规解决方案是通过扩展来增加 RAM。然而,通过减少索引占用空间,我们实现了相同的目标:最大化页面缓存中的文档数量。我们的下一步是探索索引排序,以进一步优化存储并从现有资源中获得更多性能。

相关内容

准备好打造最先进的搜索体验了吗?

足够先进的搜索不是一个人的努力就能实现的。Elasticsearch 由数据科学家、ML 操作员、工程师以及更多和您一样对搜索充满热情的人提供支持。让我们联系起来,共同打造神奇的搜索体验,让您获得想要的结果。

亲自试用