我正在使用 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
有帮助吗?

解决方案

在所有迁移应用到数据库然后耙分贝:迁移呼叫分贝:模式:转储任务来生成从当前数据库架构schema.rb文件

分贝:模式:转储调用适配器的“表”的方法来获得所有表的列表,然后为每个表称为“索引”方法和“列”方法。你可以发现,在这些方法中使用的ActiveRecord的-oracle_enhanced适配器宝石的oracle_enhanced_adapter.rb文件SQL SELECT语句。基本上它从ALL%或USER%数据字典表中选择,找到所有的信息。

起初,我曾与原甲骨文适配器问题,当我与数据库有很多不同模式的使用它(如性能可能通过表的数据库中的总人数的影响 - 不只是在你的方案),因此我做了一些优化在甲骨文增强适配器。这将是很好的找出哪些方法是很慢,你的情况(我怀疑它可以是“索引”或为每个表执行“列”方式)。

单向锄头调试此问题是,如果你把一些调试消息在oracle_enhanced_adapter.rb文件,以便您能够确定哪些方法调用要花这么长的时间。

其他提示

经过一番挖掘后,问题基本解决了 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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top