我有一个运行较旧版本的spree(一个开源购物车)的rails 3应用程序。我正在将其更新到最新版本。这要求我在数据库上运行大量迁移以与最新版本兼容。然而,应用程序当前数据库大约为300mb,并且在我的本地计算机上运行迁移(mac os x 10.7,4gb ram,2.4GHz Core 2 Duo)需要3天才能完成。
我能够使用amazon ec2实例(高I / O按需实例,四倍超大)将此时间减少到仅16小时。但是16个小时仍然很长,因为我将不得不取下网站来执行此更新。
有没有人有其他建议可以降低这段时间?或者提高迁移性能的任何提示?
仅供参考:在亚马逊实例上使用ruby 1.9.2和ubuntu。
答案 0 :(得分:3)
预先删除索引并在之后再次添加它们是一个好主意。
如上所述,同样用.find_each替换.where(...)。也许添加交易可能有所帮助。
替换.save!使用.save(:validate => false),因为在迁移期间您没有从用户那里获得随机输入,您应该进行已知良好的更新,并且验证会占用大部分执行时间。或者使用.update_attribute也会跳过只更新一个字段的验证。
尽可能在循环中使用较少的AR对象。实例化和以后的垃圾收集会占用CPU时间并占用更多内存。
答案 1 :(得分:0)
也许你已经考虑过这个:
告诉数据库不要费心确保一切都在磁盘上(没有WAL,没有fsync等),你现在有一个内存数据库应该会产生很大的不同。 (由于您已使数据库脱机,因此您可以在不太可能发生的断电或类似情况下从备份恢复)。完成后打开fsync / WAL。
在将数据库脱机之前,您可能可以执行一些迁移。当然,在暂存环境中测试这个。那个大的用户迁移很可能是现场直播。确保您不在事务中执行此操作,可能需要稍微修改它们。
我不熟悉你的具体情况,但我确信除非这还不够,否则你还可以做更多事情。
答案 2 :(得分:0)
这个答案更多的是关于方法而不是特定的技术解决方案。如果您的主要标准是最小停机时间(当然还有数据完整性),那么最好的策略是不使用rails!
相反,您可以预先完成所有繁重的工作,只留下关键的“实时”数据迁移(我在非轨道意义上使用“迁移”)作为切换期间的一个步骤。
因此,您拥有其当前应用程序及其数据库架构和生产数据。你也(大概)有一个应用程序的开发版本,它基于升级后的spree gems和新的db模式但没有数据。您所要做的就是找出一种在两者之间转换数据的方法。这可以通过多种方式完成,例如在必要时使用纯SQL和临时表,或使用SQL和ruby生成插入语句。这些步骤可以拆分,以便相当“静态”的数据(参考表,产品等)可以提前加载到数据库中,更频繁地更改的数据(用户,sesssions,订单等)可以是在迁移步骤中完成。
您应该能够编写此export-transform-import过程的脚本,以使其可重复并在完成后进行测试/检查以确保数据完整性。如果您可以在切换期间安排对新生产数据库的访问,那么应该很容易针对它运行脚本。如果您被限制在发布过程中(例如webistrano),那么您可能需要将其转换为rails迁移,但您可以使用execute运行原始SQL。
答案 3 :(得分:0)
看看这个宝石。 https://github.com/zdennis/activerecord-import/
data = []
data << Order.new(:order_info => 'test order')
Order.import data
答案 4 :(得分:0)
不幸的是,降级的解决方案是唯一的解决方案。 rails中真正慢的是activerecord模型。这不适合这样的任务。
如果您想要快速迁移,则必须在sql中执行此操作。
还有另一种方法。但是你总是要重写大部分的迁移......