2009-09-29 62 views
1

好日子所有,验证遗留表的ActiveRecord

我们正在从一个系统做数据迁移到Rails应用程序。我们正在使用的一些表格非常大,并且使用ActiveRecord一次将它们移动超过1条记录需要很长时间。因此,我们采取了在SQL中复制表并在事后进行验证。

的一个接一个的验证检查仍然很慢,但是从SQL的速度增加复制多弥补了它。但是,这并没有解决我们是否能够更快地进行验证检查的渴望。我们试图将表拆分成块,并将每个块传递给一个线程,但实际上执行速度较慢。

的问题是,大桌子,当前迭代一行一行地做验证,像这样

Model.find_each do |m| 
    logger.info "M #{m.id} is not valid" unless m.valid? 
end 

人对如何加快这什么建议?

感谢

同行

编辑我应该说,没有具体的代码。我们每个进程寻找对我们如何才能同时运行这个建议,给每个进程的数据块,而不需要一台机器

回答

0

我喜欢为起点zgchurch的响应。

我想补充的是,线程是绝对不会帮助这里,特别是因为红宝石使用绿色线程(至少在1.8.x的),所以没有机会利用多个处理器反正。即使不是这种情况,这种操作很可能是IO操作量足够大,以至于IO争用会侵入任何多核优势。

现在,如果你真的想加快这你应该看看实际的验证,并找出更有效的方式来实现这些目标。只需加载所有行并实例化一个ActiveRecord对象就会趋向于在大多数验证情况下支配性能。您可能会花费90-99.99%的时间来加载和卸载内存中的数据。

在这些类型的情况下,我倾向于去实现原始的SQL。您可以执行诸如验证外键完整性比原始ActiveRecord验证回调快几万倍的操作。当然,这种方法的可行性取决于您验证的实际情况。即使你需要的东西比SQL更丰富一点,以确定有效性,你仍然可以或许获得10-100倍的速度增加只是用更薄的SQL接口加载最小的数据,并直接检查数据。如果是这样的话,Perl或Python可能是原始性能的更好选择。

+0

好点,我一直不愿意尝试和SQL复制验证,但你可能是正确的,因为它会提供最佳性能 – 2009-10-01 13:11:43

2

find_each使用find_in_batches,它在默认情况下,一次获取1000行。您可以尝试使用batch_size选项进行播放。你有以上的方式似乎非常优化;它是从批处理数据库中获取数据并迭代每个数据库的,这些都是你需要做的。我会监视你的RAM,看看批量大小是否是最优的,如果你目前使用1.8。*,你也可以尝试使用Ruby 1.9.1来加快速度。

http://api.rubyonrails.org/classes/ActiveRecord/Batches/ClassMethods.html#M001846