Rails:rake db:migrate 在 Oracle 上*非常*慢
我使用 Rails 和 oracleenhanced
适配器来为旧应用程序创建新接口。
数据库迁移工作成功,但在 rake 完成之前需要非常长的时间。 数据库更改发生得非常快(1 或 2 秒),但 db/schema.db 转储需要一个多小时才能完成。 (请参阅下面的示例迁移。)
这是一个相对较大的架构(大约 150 个表),但我确信不应该花这么长时间来转储每个表描述。
无论如何,是否可以通过仅获取最后一个 schema.db
并将迁移中指定的更改应用到它来加快速度? 或者我可以完全跳过这个模式转储吗?
我知道这个 schema.db 用于每次从头开始创建测试数据库,但在这种情况下,表触发器中有很大一部分数据库逻辑不包含在 中无论如何,schema.rb
无论如何,rake 测试对我们来说都没有好处。 (这是一个完全不同的问题,我需要在其他时候解决。)
dgs@dgs-laptop:~/rails/voyager$ time rake db:migrate (in /home/dgs/rails/voyager) == 20090227012452 AddModuleActionAndControllerNames: migrating ================ -- add_column(:modules, :action_name, :text) -> 0.9619s -> 0 rows -- add_column(:modules, :controller_name, :text) -> 0.1680s -> 0 rows == 20090227012452 AddModuleActionAndControllerNames: migrated (1.1304s) ======= real 87m12.961s user 0m12.949s sys 0m2.128s
I'm using rails with the oracleenhanced
adaptor to create a new interface for a legacy application.
Database migrations work successfully, but take an incredibly long amount of time before rake finishes. The database changes happen pretty quickly (1 or 2 seconds), but the db/schema.db
dump takes over an hour to complete. (See example migration below.)
It's a relatively large schema (about 150 tables), but I'm sure it shouldn't be taking this long to dump out each table description.
Is there anyway to speed this up by just taking the last schema.db
and applying the change specified in the migration to it? Or am I able to skip this schema dump altogether?
I understand this schema.db
is used to create the test database from scratch each time, but this case, there's a large chunk of the database logic in table triggers which aren't included in the schema.rb
anyway, so the rake tests are no good to us in any case. (That's a whole different issue that I need to sort out at some other point.)
dgs@dgs-laptop:~/rails/voyager$ time rake db:migrate (in /home/dgs/rails/voyager) == 20090227012452 AddModuleActionAndControllerNames: migrating ================ -- add_column(:modules, :action_name, :text) -> 0.9619s -> 0 rows -- add_column(:modules, :controller_name, :text) -> 0.1680s -> 0 rows == 20090227012452 AddModuleActionAndControllerNames: migrated (1.1304s) ======= real 87m12.961s user 0m12.949s sys 0m2.128s
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
将所有迁移应用于数据库后,rake db:migrate 调用 db:schema:dump 任务以从当前数据库模式生成 schema.rb 文件。
db:schema:dump 调用适配器的“tables”方法来获取所有表的列表,然后为每个表调用“indexes”方法和“columns”方法。 您可以在 activerecord-oracle_enhanced-adapter gem 的 oracle_enhanced_adapter.rb 文件中找到这些方法中使用的 SQL SELECT 语句。 基本上它会从 ALL% 或 USER% 数据字典表中进行选择以查找所有信息。
最初,当我将原始 Oracle 适配器与具有许多不同模式的数据库一起使用时,我遇到了问题(因为性能可能会受到数据库中表总数的影响,而不仅仅是在您的模式中),因此我在 Oracle 增强版中做了一些优化适配器。 最好找出您的情况下哪些方法速度慢(我怀疑它可能是为每个表执行的“索引”或“列”方法)。
调试此问题的一种方法是,将一些调试消息放入 oracle_enhanced_adapter.rb 文件中,以便您可以确定哪些方法调用花费了很长时间。
After all migrations are applied to database then rake db:migrate calls db:schema:dump task to generate schema.rb file from current database schema.
db:schema:dump call adapter's "tables" method to get the list of all tables, then for each table calls "indexes" method and "columns" method. You can find SQL SELECT statements that are used in these methods in activerecord-oracle_enhanced-adapter gem's oracle_enhanced_adapter.rb file. Basically it does selects from ALL% or USER% data dictionary tables to find all the information.
Initially I had issues with original Oracle adapter when I used it with databases with lot of different schemas (as performance might be affected by the total number of table in the database - not just in your schema) and therefore I did some optimizations in Oracle enhanced adapter. It would be good to find out which methods are slow in your case (I suspect that it could be either "indexes" or "columns" method which is executed for each table).
One way hoe to debug this issue would be if you would put some debug messages in oracle_enhanced_adapter.rb file so that you could identify which method calls are taking so long time.
在对
oracle_enhanced_adapter.rb
进行一番深入研究后,问题基本得到解决。问题归结为本地模式中的表太多(在某个时刻同时创建了许多
EBA_%、EVT_%、EMP_%、SMP_%
表),存档表包含在转储和从数据字典中进行选择需要 14 秒才能执行。为了提高速度,我做了三件事:
这缩短了剩余 350 个表的迁移/架构转储的时间桌子从大约90分钟到大约15秒。 足够快了。
我的代码如下(为了获得灵感,不要复制和粘贴 - 该代码对于我的数据库来说是相当特定的,但您应该能够明白这个想法)。 您需要手动创建临时表。 我大约需要 2 或 3 分钟才能完成 - 每次迁移生成的时间仍然太长,而且无论如何它都是相当静态的 =)
Problem mostly solved after some digging round in
oracle_enhanced_adapter.rb
.The problem came down to way too many tables in the local schema (many
EBA_%, EVT_%, EMP_%, SMP_%
tables had been created in there coincidently at some point), archive tables being included in the dump and a select from the data dictionaries taking 14 seconds to execute.To fix the speed, I did three things:
This improved the time from the migration/schema dump for the remaining 350 tables from about 90 minutes to about 15 seconds. More than fast enough.
My code as follows (for inspiration not copying and pasting - this code is fairly specific to my database, but you should be able to get the idea). You need to create the temp table manually. It takes about 2 or 3 minutes for me to do - still too long to generate with each migration, and it's fairly static anyway =)