(2021年2月)提升 Ruby on Rails 导出 CSV 效率(耗时1小时变成耗时4分钟)

1,528次阅读
没有评论

这篇文章讲什么?

讲我最近在优化一个 Ruby on Rails 写的网站里的 csv 导出。
优化前:导出1000+行的 csv 需要1个小时。
优化后:导出8000+行的 csv 需要4分钟。

这篇文章对谁有用?有什么用?

对谁有用?正在折腾 csv 导出的 Rails 程序员
有什么用?看我是如何提升效率的

说明

由于是公司内部的系统,
因此没法贴截图。也没法贴很具体的代码。只能写文字。只能贴一两行业务无关的其他代码。

功能描述(从用户使用的视角)

  1. 用户通过各种筛选条件,筛选出他所需要的条目(可能是300条,可能是1000条,可能更多)
  2. 用户点击右上角下拉菜单的”导出为 csv”,
  3. 此时页面上方横幅文字提示 “已开始导出,完成后会通过短信通知”
  4. 用户在10分钟/30分钟/1小时左右(时间不定,取决于具体导出多少条)收到短信
  5. 用户进入同一个页面里 “导出为 csv” 下方的那一条 “导出历史”
  6. 用户在 “导出历史” 页面可以看到刚刚那条导出任务,点击右侧的 “下载”
  7. 下载得到一个 csv 文件

整个流程完成。

实现方法(从程序的角度)

  1. 用户点击”导出为 csv”会添加一个后台任务(background job)
  2. 后台任务里生成 csv 文件,然后把文件上传到 AWS S3 存着
  3. 把文件地址保存到数据库里,发短信通知用户,程序就此结束。

2月也放假了懒得写那么多细节,直接来重点

  1. 我们之前用的后台队列是 que,为了解决这个问题换成了 sidekiq,我个人认为对提升效率有一定帮助,但不是主要原因,只不过把 que 换成 sidekiq 这个事情是迟早要做的,这次就顺手做了。

  2. 尽量降低数据库的查询次数(有点算是废话,但还是要强调的)之前我们导出单个条目,需要23次数据库查询(我直接本地试一下然后看 log/development.log 就知道了),经过优化后降低到了7次(没法再降低了,因为数据的确存在7张不同的表里)

  3. 不要往内存里存一整个 csv 文件(不过这个对我们的影响也没那么大,实际导出8000+行数据得到的 csv 文件也才15MB)生成多少就直接往硬盘上写

  4. 使用 ActiveRecord::Base.connection.uncached
    这个是影响因素最大的。

ActiveRecord::Base.connection.uncached do
# 把代码这样包起来
end

# 返回一个 Tempfile
def self.csv(application_ids, user_id)
temp_file = Tempfile.new(‘export_application_csv’)
# 最有效减低内存消耗的是 ActiveRecord::Base.connection.uncached 这一句
ActiveRecord::Base.connection.uncached do # https://github.com/rails/rails/issues/27002#issuecomment-260086170
CSV.open(temp_file.path, ‘w’, write_headers: true, headers: get_headers()) do |csv|
application_ids.each do |a_id|
application = Apply::Application.find_by(id: a_id)
one_row = answer_for_each_application(application)
csv << one_row
csv.flush # https://stackoverflow.com/questions/34168814/does-rubys-csv-open-buffer-to-memory-and-write-all-at-once
end
end
end
return temp_file
end

其他试过但是不管用的方法

  • find_each 方法试过了,好像帮助不大(从内存占用角度而言)
  • 哪怕从 que 换成了 sidekiq,如果不用 ActiveRecord::Base.connection.uncached 内存占用会从 180MB(平时没任务的时候就是这么大,可以在 Sidekiq Web UI 里面看到)
    上升到 2047MB。

结论

用 ActiveRecord::Base.connection.uncached 让 Rails 不要缓存。
在各种方法里是最有效的提升速度的方法

这篇文章讲什么?

讲我最近在优化一个 Ruby on Rails 写的网站里的 csv 导出。
优化前:导出1000+行的 csv 需要1个小时。
优化后:导出8000+行的 csv 需要4分钟。

这篇文章对谁有用?有什么用?

对谁有用?正在折腾 csv 导出的 Rails 程序员
有什么用?看我是如何提升效率的

说明

由于是公司内部的系统,
因此没法贴截图。也没法贴很具体的代码。只能写文字。只能贴一两行业务无关的其他代码。

功能描述(从用户使用的视角)

  1. 用户通过各种筛选条件,筛选出他所需要的条目(可能是300条,可能是1000条,可能更多)
  2. 用户点击右上角下拉菜单的”导出为 csv”,
  3. 此时页面上方横幅文字提示 “已开始导出,完成后会通过短信通知”
  4. 用户在10分钟/30分钟/1小时左右(时间不定,取决于具体导出多少条)收到短信
  5. 用户进入同一个页面里 “导出为 csv” 下方的那一条 “导出历史”
  6. 用户在 “导出历史” 页面可以看到刚刚那条导出任务,点击右侧的 “下载”
  7. 下载得到一个 csv 文件

整个流程完成。

实现方法(从程序的角度)

  1. 用户点击”导出为 csv”会添加一个后台任务(background job)
  2. 后台任务里生成 csv 文件,然后把文件上传到 AWS S3 存着
  3. 把文件地址保存到数据库里,发短信通知用户,程序就此结束。

2月也放假了懒得写那么多细节,直接来重点

  1. 我们之前用的后台队列是 que,为了解决这个问题换成了 sidekiq,我个人认为对提升效率有一定帮助,但不是主要原因,只不过把 que 换成 sidekiq 这个事情是迟早要做的,这次就顺手做了。

  2. 尽量降低数据库的查询次数(有点算是废话,但还是要强调的)之前我们导出单个条目,需要23次数据库查询(我直接本地试一下然后看 log/development.log 就知道了),经过优化后降低到了7次(没法再降低了,因为数据的确存在7张不同的表里)

  3. 不要往内存里存一整个 csv 文件(不过这个对我们的影响也没那么大,实际导出8000+行数据得到的 csv 文件也才15MB)生成多少就直接往硬盘上写

  4. 使用 ActiveRecord::Base.connection.uncached
    这个是影响因素最大的。

ActiveRecord::Base.connection.uncached do
# 把代码这样包起来
end

# 返回一个 Tempfile
def self.csv(application_ids, user_id)
temp_file = Tempfile.new(‘export_application_csv’)
# 最有效减低内存消耗的是 ActiveRecord::Base.connection.uncached 这一句
ActiveRecord::Base.connection.uncached do # https://github.com/rails/rails/issues/27002#issuecomment-260086170
CSV.open(temp_file.path, ‘w’, write_headers: true, headers: get_headers()) do |csv|
application_ids.each do |a_id|
application = Apply::Application.find_by(id: a_id)
one_row = answer_for_each_application(application)
csv << one_row
csv.flush # https://stackoverflow.com/questions/34168814/does-rubys-csv-open-buffer-to-memory-and-write-all-at-once
end
end
end
return temp_file
end

其他试过但是不管用的方法

  • find_each 方法试过了,好像帮助不大(从内存占用角度而言)
  • 哪怕从 que 换成了 sidekiq,如果不用 ActiveRecord::Base.connection.uncached 内存占用会从 180MB(平时没任务的时候就是这么大,可以在 Sidekiq Web UI 里面看到)
    上升到 2047MB。

结论

用 ActiveRecord::Base.connection.uncached 让 Rails 不要缓存。
在各种方法里是最有效的提升速度的方法

 

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)

文心AIGC

2023 年 3 月
 12345
6789101112
13141516171819
20212223242526
2728293031  
文心AIGC
文心AIGC
人工智能ChatGPT,AIGC指利用人工智能技术来生成内容,其中包括文字、语音、代码、图像、视频、机器人动作等等。被认为是继PGC、UGC之后的新型内容创作方式。AIGC作为元宇宙的新方向,近几年迭代速度呈现指数级爆发,谷歌、Meta、百度等平台型巨头持续布局
文章搜索
热门文章
清库存!DeepSeek突然补全R1技术报告,训练路径首次详细公开

清库存!DeepSeek突然补全R1技术报告,训练路径首次详细公开

清库存!DeepSeek突然补全R1技术报告,训练路径首次详细公开 Jay 2026-01-08 20:18:...
训具身模型遇到的很多问题,在数据采集时就已经注定了丨鹿明联席CTO丁琰分享

训具身模型遇到的很多问题,在数据采集时就已经注定了丨鹿明联席CTO丁琰分享

训具身模型遇到的很多问题,在数据采集时就已经注定了丨鹿明联席CTO丁琰分享 衡宇 2026-01-08 20:...
开源“裸考”真实世界,国产具身智能基座模型拿下全球第二!

开源“裸考”真实世界,国产具身智能基座模型拿下全球第二!

开源“裸考”真实世界,国产具身智能基座模型拿下全球第二! 西风 2026-01-08 19:02:20 来源:...
「北京版幻方」冷不丁开源SOTA代码大模型!一张3090就能跑,40B参数掀翻Opus-4.5和GPT-5.2

「北京版幻方」冷不丁开源SOTA代码大模型!一张3090就能跑,40B参数掀翻Opus-4.5和GPT-5.2

「北京版幻方」冷不丁开源SOTA代码大模型!一张3090就能跑,40B参数掀翻Opus-4.5和GPT-5.2...
最新评论
ufabet ufabet มีเกมให้เลือกเล่นมากมาย: เกมเดิมพันหลากหลาย ครบทุกค่ายดัง
tornado crypto mixer tornado crypto mixer Discover the power of privacy with TornadoCash! Learn how this decentralized mixer ensures your transactions remain confidential.
ดูบอลสด ดูบอลสด Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
ดูบอลสด ดูบอลสด Pretty! This has been a really wonderful post. Many thanks for providing these details.
ดูบอลสด ดูบอลสด Pretty! This has been a really wonderful post. Many thanks for providing these details.
ดูบอลสด ดูบอลสด Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
Obrazy Sztuka Nowoczesna Obrazy Sztuka Nowoczesna Thank you for this wonderful contribution to the topic. Your ability to explain complex ideas simply is admirable.
ufabet ufabet Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
ufabet ufabet You’re so awesome! I don’t believe I have read a single thing like that before. So great to find someone with some original thoughts on this topic. Really.. thank you for starting this up. This website is something that is needed on the internet, someone with a little originality!
ufabet ufabet Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
热评文章
首家央企AI独角兽浮出水面!背靠自研大模型,4家国家队资本背书

首家央企AI独角兽浮出水面!背靠自研大模型,4家国家队资本背书

首家央企AI独角兽浮出水面!背靠自研大模型,4家国家队资本背书 Jay 2026-01-07 15:24:04...
悲报!Stack Overflow彻底凉了,比18年前上线首月问题数量还少

悲报!Stack Overflow彻底凉了,比18年前上线首月问题数量还少

悲报!Stack Overflow彻底凉了,比18年前上线首月问题数量还少 闻乐 2026-01-05 19:...
老黄All in物理AI!最新GPU性能5倍提升,还砸掉了智驾门槛

老黄All in物理AI!最新GPU性能5倍提升,还砸掉了智驾门槛

老黄All in物理AI!最新GPU性能5倍提升,还砸掉了智驾门槛 闻乐 2026-01-06 09:09:0...
OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex

OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex

OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex 衡宇 2026-01-06 13:0...
OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex

OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex

OpenAI推理第一人离职,7年打造了o3/o1/GPT-4/Codex 衡宇 2026-01-06 13:0...