我正在使用带oracleenhanced
适配器的rails为旧版应用程序创建一个新界面。
数据库迁移成功完成,但在rake完成之前需要花费相当长的时间。数据库更改发生得非常快(1或2秒),但db/schema.db
转储需要一个多小时才能完成。 (参见下面的示例迁移。)
这是一个相对较大的架构(约150个表),但我确信不应该花这么长时间来转储每个表格描述。
无论如何只需要使用最后一个schema.db
并将迁移中指定的更改应用到它来加快速度吗?或者我能够完全跳过这个模式转储吗?
我理解这个schema.db
每次都是从头开始创建测试数据库,但是这种情况下,表触发器中有很大一部分数据库逻辑没有包含在schema.rb
中无论如何,所以在任何情况下,佣金测试对我们都没有好处。 (这是一个完全不同的问题,我需要在其他方面进行梳理。)
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
答案 0 :(得分:4)
将所有迁移应用于数据库之后,然后rake db:migrate调用db:schema:dump task从当前数据库模式生成schema.rb文件。
db:schema:dump call adapter的“tables”方法获取所有表的列表,然后为每个表调用“索引”方法和“列”方法。您可以在activerecord-oracle_enhanced-adapter gem的oracle_enhanced_adapter.rb文件中找到这些方法中使用的SQL SELECT语句。基本上它确实从ALL%或USER%数据字典表中选择以查找所有信息。
最初,当我将其用于具有大量不同模式的数据库时,我遇到了原始Oracle适配器的问题(因为性能可能会受到数据库中表的总数的影响 - 而不仅仅是在您的模式中),因此我做了一些优化在Oracle增强适配器中。在你的情况下找出哪些方法很慢会很好(我怀疑它可能是为每个表执行的“索引”或“列”方法)。
调试此问题的一种方法是,如果您在oracle_enhanced_adapter.rb文件中放入一些调试消息,以便您可以识别哪些方法调用花了这么长时间。
答案 1 :(得分:2)
问题主要是在oracle_enhanced_adapter.rb
进行一些挖掘后解决的。
问题归结为本地模式中的表太多(在某些时候恰好创建了许多EBA_%, EVT_%, EMP_%, SMP_%
表),转储中包含的归档表和数据字典中的选择执行14秒。
为了确定速度,我做了三件事:
这将剩余350个表的迁移/模式转储的时间从大约90分钟缩短到大约15秒。比足够快。
我的代码如下(灵感不是复制和粘贴 - 这段代码对我的数据库非常具体,但你应该能够理解)。您需要手动创建临时表。我需要大约2到3分钟的时间 - 每次迁移仍然需要太长时间,而且无论如何它都是相当静态的=)
module ActiveRecord
module ConnectionAdapters
class OracleEnhancedAdapter
def tables(name = nil)
select_all("select lower(table_name) from all_tables where owner = sys_context('userenv','session_user') and table_name not like 'A!_%' escape '!' ").inject([]) do | tabs, t |
tabs << t.to_a.first.last
end
end
# TODO think of some way to automatically create the rails_temp_index table
#
# Table created by:
# create table rails_temp_index_table as
# SELECT lower(i.index_name) as index_name, i.uniqueness,
# lower(c.column_name) as column_name, i.table_name
# FROM all_indexes i, user_ind_columns c
# WHERE c.index_name = i.index_name
# AND i.owner = sys_context('userenv','session_user')
# AND NOT exists (SELECT uc.index_name FROM user_constraints uc
# WHERE uc.constraint_type = 'P' and uc.index_name = i.index_name);
def indexes(table_name, name = nil) #:nodoc:
result = select_all(<<-SQL, name)
SELECT index_name, uniqueness, column_name
FROM rails_temp_index_table
WHERE table_name = '#{table_name.to_s.upcase}'
ORDER BY index_name
SQL
current_index = nil
indexes = []
result.each do |row|
if current_index != row['index_name']
indexes << IndexDefinition.new(table_name, row['index_name'], row['uniqueness'] == "UNIQUE", [])
current_index = row['index_name']
end
indexes.last.columns << row['column_name']
end
indexes
end
end