mysql - 优化代码以在一个巨大的表中填充一个新列

标签 mysql ruby-on-rails ruby

我要向具有 3700 万行的表添加一个新列。该列将包含一个关联 ID。

简单模型:

class SeenEpisode < ActiveRecord::Base
  #show_id is the new column
  attr_accessible :user_id, :season_id, :episode_id, :show_id
  belongs_to :episode
  belongs_to :season
end

这是我能想到的最快的方法:

seen_episodes = SeenEpisode.where("show_id IS NULL")
seen_episodes.find_in_batches do |batch| #batch size is 1000
  batch.group_by(&:season_id).each do |season_id, seen_episodes|
    #all seen_episodes with the same season_id, ensures the same show_id
    show_id = seen_episodes.first.episode.show_id
    seen_episodes.each do |seen_episode|
      seen_episode.update_column(:show_id, show_id) #skip validations and callbacks
    end
  end
end

目前的开发测试表明,填充 10.000 条记录大约需要 2 分钟。
假设生产环境需要 1 分钟,由于更好的硬件和 mysql 配置,每百万条记录仍需要 100 分钟。大约 60 小时。

有没有可能有更快的方法来解决这个问题?

最佳答案

如果您批量写入,速度会快几个数量级。我的意思是,而不是发送单独的写入

update episodes set show_id = 1 where episode_id = 1;
update episodes set show_id = 1 where episode_id = 2;
update episodes set show_id = 1 where episode_id = 3;

你应该把它们组合成一个单独的写

update episodes set show_id = 1 where episode_id in (1, 2, 3);

或者,像这样的东西可以工作:

select season_id, show_id 
from episodes 
where show_id is not null 
group by season_id;

那应该为每个 season_id 获取一个 show_id。然后循环遍历这些行并触发大量更新(为简单起见,SQL 语法,您可能会在 ruby​​ 中执行此操作)

update episodes set show_id = @show_id where season_id = @season_id;

关于mysql - 优化代码以在一个巨大的表中填充一个新列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16748396/

相关文章:

ruby-on-rails - ruby 模块作为方法的集合

ruby-on-rails - ActiveRecord 究竟如何期望日期被格式化

mysql - 在 Wamp 上安装 MySQL 插件

mysql - 使用 Laravel 构建器同时为子查询、过滤器、计数创建查询

mysql - 实例 (Param B.ByteString) 是如何消失的?

ruby-on-rails - omn​​iauth facebook 不显示图片

ruby-on-rails - 覆盖渲染 :json in no model object Rails 4

ruby-on-rails - 读入文件内容rails

ruby-on-rails - Rails 如何创建 cookie 并稍后调用数据?

mysql - 数据库magento中 "Static blocks"和 "Cms pages"的表名?