【问题标题】:Rails: rake db:migrate *very* slow on OracleRails: rake db:migrate *very* 在 Oracle 上很慢
【发布时间】:2010-10-10 04:44:32
【问题描述】:

我正在使用带有oracleenhanced 适配器的rails 来为旧应用程序创建一个新接口。

数据库迁移成功运行,但在 rake 完成之前需要很长时间。数据库更改发生得非常快(1 或 2 秒),但 db/schema.db 转储需要一个多小时才能完成。 (请参阅下面的示例迁移。)

这是一个相对较大的架构(大约 150 个表),但我确信转储每个表描述不应该花这么长时间。

有没有办法通过只取最后一个schema.db 并将迁移中指定的更改应用于它来加快速度?或者我可以完全跳过这个模式转储吗?

我知道 schema.db 每次都用于从头开始创建测试数据库,但是在这种情况下,表触发器中有很大一部分数据库逻辑不包含在 schema.rb 中,所以无论如何,rake 测试对我们都没有好处。 (这是一个完全不同的问题,我需要在其他时候解决。)

dgs@dgs-laptop:~/rails/voyager$ time rake db:migrate (在 /home/dgs/rails/voyager 中) == 20090227012452 AddModuleActionAndControllerNames:迁移 ================ -- add_column(:modules, :action_name, :text) -> 0.9619s -> 0 行 -- add_column(:modules, :controller_name, :text) -> 0.1680 秒 -> 0 行 == 20090227012452 AddModuleActionAndControllerNames:迁移(1.1304s)======= 真正的 87m12.961s 用户 0m12.949s 系统 0m2.128s

【问题讨论】:

    标签: ruby-on-rails ruby oracle rake dbmigrate


    【解决方案1】:

    在所有迁移应用到数据库之后,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 文件中,以便确定哪些方法调用需要这么长时间。

    【讨论】:

    • 酷。我将在 oracle_enhanced_adapter.rb 中试一试,看看我能找到什么。我怀疑它与架构相关联,因为数据库中有许多相同的架构具有不同的名称。干杯
    • 您也可以尝试新的 oracle_enhanced 适配器版本 1.2.0 - 架构转储性能有一些改进。
    【解决方案2】:

    oracle_enhanced_adapter.rb 中进行了几轮挖掘之后,问题基本解决了。

    问题归结为本地架构中的表太多(许多EBA_%, EVT_%, EMP_%, SMP_% 表已在某个时候同时创建在那里),存档表包含在转储中,并且从数据字典中进行选择需要 14 秒执行。

    为了提高速度,我做了三件事:

    1. 删除了所有不需要的表(大约 500 个表中的 250 个)
    2. 从模式转储中排除存档表
    3. 缓存了长时间运行的查询结果

    这将剩余 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
    

    【讨论】:

      猜你喜欢
      • 2016-11-19
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 1970-01-01
      • 2018-10-06
      • 2011-07-14
      • 2014-04-30
      相关资源
      最近更新 更多