ES 数据插入速度优化
2023-8-4
| 2024-9-29
0  |  Read Time 0 min
type
status
date
slug
summary
tags
category
icon
password
 
写了个脚本把数据库里面的 content 字段转换为向量插入到 ES, 100w 数据需要 4.5 小时,太慢了!!!
 

一、慢速度脚本(4.5h)

只用 aiomysql 对数据库进行异步请求,ES 更新则是一条一更新。
运行截图(4h 30m 21s):
notion image

二、初步优化(1h)

安装 elasticsearch[async] 模块
使用 es bulk 批量更新数据,加速数据插入。
运行截图(1h 3m 9s):
notion image

三、内存优化

优化目的:减少内存使用
优化策略:
  • 使用 async_streaming_bulk 代替 async_bulk
  • 使用 asyncio.as_completed 代替 asyncio.gather
async_streaming_bulk 和 async_bulk 的区别:
  • async_bulk 会将所有请求收集到一个列表中,然后一次性发送给 Elasticsearch,它会等待所有的请求完成,然后返回结果。
  • async_streaming_bulk 则是一边收集请求,一边流式地发送给 Elasticsearch,不需要等待所有的请求收集完成,它会实时返回每个请求的结果。
  • async_bulk 适用于需要等待所有请求完成才返回的场景,但是需要消耗更多内存来 hold 住所有请求。
  • async_streaming_bulk 适用于对实时返回每个结果更敏感的场景,它消耗的内存更少。
  • sync_bulk 的性能会比 async_streaming_bulk 好,因为它是批量发送请求。但是 async_streaming_bulk 更适合处理大量请求,不会因为内存消耗太大而出问题。
asyncio.as_completed 和 asyncio.gather 的区别:
  • asyncio.gather 会同时启动所有的异步任务,等待它们全部完成后才返回结果。
  • asyncio.as_completed 会按任务完成的顺序返回结果,不会等待所有的任务完成。
  • asyncio.gather 如果有一个任务 raise 异常会立即停止其它任务。asyncio.as_completed 不会,会继续返回其它已经完成的任务的结果。
  • asyncio.gather 的结果顺序和传入的任务顺序一致。asyncio.as_completed 的结果顺序依赖于任务完成的时间,与传入顺序无关。
  • asyncio.gather 更适合需要同时开始执行多个任务,并需要所有任务结果才能继续的场景。asyncio.as_completed 更适合只关心任务完成就使用结果的场景。
  • asyncio.gather 的性能和资源消耗可能更高,因为同时启动和跟踪更多任务。
  • asyncio.as_completed 可以通过返回完成任务来提早优化或发出决策。
优化后的代码:
运行截图(59m 28s):
notion image
  • 优化
  • ES 数据迁移TiDB 数据导入之 tidb lightning
    Loading...