19

我有一个运行旧版本 Spree(开源购物车)的 Rails 3 应用程序。我正在将其更新到最新版本。这需要我在数据库上运行大量迁移以与最新版本兼容。然而,应用程序当前的数据库大约是 300mb,并且在我的本地机器(mac os x 10.7、4gb ram、2.4GHz Core 2 Duo)上运行迁移需要三天才能完成。

我能够使用 Amazon EC2 实例(高 I/O 按需实例,四倍超大)将这个时间减少到仅 16 小时。但是 16 小时仍然太长,因为我必须关闭网站才能执行此更新。

有没有人有任何其他建议来降低这个时间?或者有什么技巧可以提高迁移的性能?

仅供参考:在 Amazon 实例上使用 Ruby 1.9.2 和 Ubuntu。

4

5 回答 5

3
  • 事先删除索引并在之后再次添加它们是一个好主意。

  • 如前所述,还将 .where(...).each 替换为 .find_each 并添加事务可能会有所帮助。

  • 替换.save!使用 .save(:validate => false),因为在迁移期间您没有从用户那里获得随机输入,您应该进行已知良好的更新,并且验证占了大部分执行时间。或者使用 .update_attribute 也会跳过只更新一个字段的验证。

  • 在可能的情况下,在循环中使用更少的 AR 对象。实例化和稍后的垃圾收集会占用 CPU 时间并使用更多内存。

于 2012-08-02T13:45:21.587 回答
0

也许你已经考虑过这个:

  1. 告诉数据库不要费心确保一切都在磁盘上(没有 WAL,没有 fsync 等),你现在有一个内存数据库,这应该会产生很大的不同。(由于您已使数据库脱机,因此您可以在不太可能发生断电或类似情况的情况下从备份中恢复)。完成后打开 fsync/WAL。

  2. 在使数据库脱机之前,您可能可以进行一些迁移。当然,在 staging 环境中进行测试。大用户迁移很可能会实时进行。确保您不在事务中执行此操作,您可能需要对它们进行一些修改。

我不熟悉你的具体情况,但我相信你可以做更多的事情,除非这还不够。

于 2012-07-26T23:58:30.890 回答
0

不幸的是,降级的解决方案是唯一的。rails 中真正慢的是 activerecord 模型。不适合这样的任务。

如果您想要快速迁移,则必须在 sql 中进行。

还有另一种方法。但是你总是需要重写大部分迁移......

于 2012-08-23T12:17:53.220 回答
0

这个答案更多的是关于方法而不是特定的技术解决方案。如果您的主要标准是最短停机时间(当然还有数据完整性),那么最好的策略就是不使用 Rails!

相反,您可以预先完成所有繁重的工作,并将关键的“实时”数据迁移(我在这里使用非 Rails 意义上的“迁移”)作为切换过程中的一个步骤。

因此,您拥有当前的应用程序及其数据库架构和生产数据。您还(可能)拥有基于升级的 spree gem 的应用程序开发版本,具有新的 db 模式但没有数据。您所要做的就是找出一种在两者之间转换数据的方法。这可以通过多种方式完成,例如在必要时使用纯 SQL 和临时表或使用 SQL 和 ruby​​ 生成插入语句。这些步骤可以拆分,以便可以提前将相当“静态”的数据(参考表、产品等)加载到数据库中,并且可以将更频繁更改的数据(用户、会话、订单等)在迁移步骤中完成。

您应该能够编写此导出-转换-导入过程的脚本,使其可重复,并在完成后进行测试/检查以确保数据完整性。如果您可以在切换期间安排对新生产数据库的访问,那么对它运行脚本应该很容易。如果您受限于发布过程(例如 webistrano),那么您可能不得不将其硬塞到 Rails 迁移中,但您可以使用 execute 运行原始 SQL。

于 2012-07-29T05:49:49.393 回答
0

看看这个宝石。 https://github.com/zdennis/activerecord-import/

data = []
data << Order.new(:order_info => 'test order')
Order.import data
于 2012-08-05T22:02:37.833 回答