Pergunta

Eu estou usando rails com o adaptador oracleenhanced para criar uma nova interface para um aplicativo de legado.

migrações de banco de dados trabalhar com sucesso, mas levar um tempo incrivelmente longo período de tempo antes acabamentos de rake. As mudanças de banco de dados acontecer muito rapidamente (1 ou 2 segundos), mas o despejo db/schema.db leva mais de uma hora para ser concluído. (Veja o exemplo de migração abaixo).

É uma relativamente grande esquema (cerca de 150 mesas), mas eu tenho certeza que ele não deveria estar tomando tanto tempo para despejar a descrição de cada mesa.

Existe uma maneira de acelerar isso por apenas tomando o último schema.db e aplicar a alteração especificada na migração para isso? Ou eu sou capaz de saltar esta despejo esquema completamente?

Eu entendo isso schema.db é usado para criar o banco de dados de teste a partir do zero cada vez, mas neste caso, há um grande pedaço da lógica de banco de dados em gatilhos de mesa que não estão incluídos no schema.rb qualquer maneira, então os testes de inclinação não são bom para nós, em qualquer caso. (Isso é uma questão totalmente diferente que eu preciso para resolver em algum outro ponto.)

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
Foi útil?

Solução

Depois de todas as migrações são aplicadas ao banco de dados, então rake db: chamadas Migrar db: schema:. Tarefa de despejo para gerar o arquivo schema.rb de esquema de banco de dados atual

db: schema: método de "tabelas" do adaptador de chamada despejo para obter a lista de todas as tabelas, em seguida, para cada tabela chamadas "índices" Método e método "colunas". Você pode encontrar instruções SQL SELECT que são usados ??nestes métodos no arquivo oracle_enhanced_adapter.rb-adaptador oracle_enhanced-activerecord da jóia. Basicamente ele faz seleciona TODAS% ou usuário% de dados tabelas de dicionário para encontrar todas as informações.

Inicialmente I teve problemas com o adaptador do Oracle original quando eu usei-o com bancos de dados com muitos esquemas diferentes (como o desempenho pode ser afetado pelo número total de tabela no banco de dados - e não apenas no seu esquema) e, portanto, eu fiz algumas otimizações no Oracle reforçada adaptador. Seria bom para descobrir quais métodos são lentos no seu caso (Eu suspeito que poderia ser ou "índices" ou método de "colunas", que é executado para cada tabela).

Uma forma enxada para depurar este problema seria se você colocar algumas mensagens de depuração no arquivo oracle_enhanced_adapter.rb para que você possa identificar quais chamadas de método está tomando tanto tempo.

Outras dicas

Problema principalmente resolvido depois de algum rodada escavação em oracle_enhanced_adapter.rb.

O problema veio para baixo a maneira muitas tabelas no esquema local (muitas mesas EBA_%, EVT_%, EMP_%, SMP_% tinha sido criado lá coincidentemente em algum ponto), mesas de arquivo a ser incluído no despejo e uma escolha dos dicionários de dados, tendo 14 segundos para executar .

Para corrigir a velocidade, eu fiz três coisas:

  1. Caiu todas as tabelas desnecessários (cerca de 250 de 500)
  2. tabelas de arquivo excluídos da despejo de esquema
  3. Em cache o resultado da corrida de longa consulta

Isso melhorou o tempo do despejo de migração / esquema para os restantes 350 mesas de cerca de 90 minutos a cerca de 15 segundos. Mais do que suficiente rápido.

Meu código da seguinte forma (para a inspiração não copiando e colando - este código é bastante específico para meu banco de dados, mas você deve ser capaz de obter a idéia). Você precisa criar a tabela temporária manualmente. Demora cerca de 2 ou 3 minutos para eu fazer - ainda muito tempo para gerar com cada migração, e é de qualquer maneira bastante estática =)

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top