我使用Ruby on Rails为遗留(供应商)数据库开发了一个Web界面。数据库模式完全混乱,> 450个表,客户数据超过20个,涉及复杂的连接等。
我为网络应用程序提供了一个很好的解决方案,它运行良好。但我们也从外部数据源(目前是SQL Server数据库和SOAP提要的视图)进行夜间导入,并且它们运行SLOW。 XML数据导入大约需要1.5-2.5小时,数据库导入大约需要4小时。
这是在做了一些基本的优化之后,包括手动启动MRI垃圾收集器。那就是对我来说,我做错了。我考虑过将夜间更新/插入任务从主Rails应用程序中移出,并尝试使用JRuby或Rubinius来利用更好的并发和垃圾收集。
我的问题是:我知道ActiveRecord并不是专门为这类任务设计的。但是在Ruby(我的首选语言)的O / RM选项中,它似乎拥有最好的Oracle支持。
你会做什么?坚持使用AR并使用不同的翻译?这真的有帮助吗? DataMapper或Sequel怎么样?有没有更好的方法呢?我愿意使用Scala或Clojure,如果有更好的选择(不限于,但这些是我现在正在玩的其他语言)......但我不想要的就像DBI我正在编写直接SQL,如果没有其他原因,供应商更新偶尔会更改数据库模式,我宁愿更改几个类而不是数百个UPDATE或INSERT语句。
希望这个问题不是“太模糊”,但我真的可以对这个问题使用一些建议。
FWIW,Ruby是1.9.2,Rails是3.0.7,平台是OS X Server Snow Leopard(或者可选的Debian 6.0)。
答案 0 :(得分:2)
根据我的经验,ORM是一个很好的工具,可以在前端使用,您只需要一次读取数据或更新一行。在您一次摄取数据丢失的后端,由于它们倾向于与数据库交互的方式,它们可能会导致问题。
作为一个例子,假设你有一个Person对象,其中包含一个很长的Friends列表(现在就说100)。您创建Person对象并为其分配100个朋友,然后将其保存到数据库。通常使用ORM对数据库进行101次写入(每个朋友一个,一个人为人)。如果你在较低级别的纯SQL中执行此操作,则需要执行2次写入,一次写入Person,然后一次写入所有Friends(一次插入100个实际行)。这两个行动之间的差异很大。
我见过几种方法可以解决这个问题。
主要的一点是,使用ORM来摄取任何实际大小的数据可能会遇到效率问题。了解ORM正在做什么(要求它记录所有数据库调用是了解它正在做什么的一个好方法)是最好的第一步。一旦你知道它在做什么,你就可以找到方法告诉它“我正在做的事情并不适合正常模式,让我们改变你使用它的方式”......并且,如果没有可行的方法,您可以使用较低级别的API来考虑它。
我会指出另一件事你可以用 STRONG 警告来看,它应该是你考虑的最后一件事。在批量插入数据库时,您可以创建包含所有数据的原始文本文件(格式取决于数据库,但概念类似于CSV文件)并将文件提供给数据库以批量导入。几乎在每种情况下这都是一种糟糕的方式,但我想要包含它,因为它确实存在。
编辑:作为旁注,关于更有效地解析XML的评论也是一件好事。使用SAX与DOM或不同的XML库,可以在完成时获得巨大的胜利。在某些情况下,它可能比更有效的数据库交互更大的胜利。例如,您可能正在解析大量具有大量小数据的XML,然后只使用它的一小部分。在这样的情况下,解析可能需要很长时间通过DOM,而SAX可以忽略你不需要的部分......或者它可能使用大量内存创建DOM对象并减慢由于垃圾的整个事情收集等等。至少,它值得一看。
答案 1 :(得分:2)
编辑 确定刚刚意识到此解决方案无法用于oracle,抱歉---
你应该检查出ActiveRecord-Import,它很容易使用并使用最少量的sql语句处理批量导入。我看到加速从5小时到2分钟。它仍然会对数据进行验证。
来自github页面:
books = []
10.times do |i|
books << Book.new(:name => "book #{i}")
end
Book.import books
答案 2 :(得分:1)
由于您的问题确实“有点模糊”,我只建议您使用XML Pull解析来优化XML导入。
看看这个: https://gist.github.com/827475
我需要导入MySQL XML,并且公平地说,使用XML Pull方法将解析部分提高了大约7倍(是的,几乎比读取内存中的整个内容快7倍)。
另一件事:你说“数据库导入需要4个小时”。您要导入的这些数据库导出文件格式是什么?