Domanda

Sto usando le rotaie con l'adattatore oracleenhanced per creare una nuova interfaccia per un'applicazione legacy.

migrazioni di database lavorare con successo, ma prendono un tempo incredibilmente lungo periodo di tempo prima di finiture rastrello. Le modifiche al database avvengono abbastanza rapidamente (1 o 2 secondi), ma la discarica db/schema.db prende più di un'ora per completare. (Vedi sotto esempio di migrazione.)

E 'un relativamente grande schema (circa 150 tavoli), ma sono sicuro che non dovrebbe prendere questo lungo per fare uscire fuori ogni descrizione della tabella.

Esiste un modo per accelerare questo da solo prendendo l'ultimo schema.db e applicando la variazione specificato nella migrazione ad esso? O sono in grado di saltare questo schema discarica del tutto?

ho capito questo schema.db viene utilizzato per creare il database di test da zero ogni volta, ma questo caso, c'è un grande pezzo della logica del database nella tabella trigger che non sono inclusi nel schema.rb comunque, quindi i test rastrello esistono buono con noi in ogni caso. (Che è tutta una questione diversa che ho bisogno di risolvere in qualche altro punto.)

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
È stato utile?

Soluzione

Dopo tutte le migrazioni vengono applicate al database di poi rake db: migrate chiamate db: schema:. Compito discarica per generare file di schema.rb da schema di database corrente

db: schema: il metodo della scheda chiamata dump "tabelle" per ottenere l'elenco di tutte le tabelle, quindi per ogni tabella chiama il metodo "indici" e il metodo di "colonne". Si possono trovare istruzioni SQL SELECT che vengono utilizzati in questi metodi nel file di oracle_enhanced_adapter.rb activerecord-oracle_enhanced adattatore del gioiello. Fondamentalmente lo fa sceglie di tutte le tabelle% o del dizionario% i dati degli utenti per trovare tutte le informazioni.

Inizialmente ho avuto problemi con adattatore originale Oracle quando l'ho usato con i database con il lotto di schemi diversi (come le prestazioni potrebbe essere influenzata dal numero totale di tabella nel database - non solo nello schema) e, pertanto, ho fatto alcune ottimizzazioni in Oracle migliorato adattatore. Sarebbe bene sapere quali metodi sono lenti nel tuo caso (ho il sospetto che potrebbe essere sia "indici" o metodo "colonne", che viene eseguito per ogni tabella).

Un modo per eseguire il debug zappa questo problema sarebbe se si sarebbe messo alcuni messaggi di debug nel file di oracle_enhanced_adapter.rb in modo da poter identificare quali chiamate di metodo sta prendendo così tanto tempo.

Altri suggerimenti

Problemi principalmente risolto dopo qualche giro scavo in oracle_enhanced_adapter.rb.

Il problema è venuto giù a troppi tavoli nello schema locale (molte tabelle EBA_%, EVT_%, EMP_%, SMP_% erano stati creati in là casualmente ad un certo punto), le tabelle di archivio di essere inclusi nella discarica e una selezione da dizionari di dati che prendono 14 secondi per eseguire .

Per risolvere la velocità, ho fatto tre cose:

  1. Dropped tutte le tabelle non necessarie (circa 250 su 500)
  2. tabelle di archivio esclusi dalla discarica schema
  3. Copia cache il risultato della query in esecuzione lungo

Questo ha migliorato il tempo dalla discarica di migrazione / schema per i restanti 350 tabelle da circa 90 minuti per circa 15 secondi. Più che abbastanza veloce.

Il mio codice come segue (per ispirazione non copia e incolla - questo codice è abbastanza specifico per il mio database, ma si dovrebbe essere in grado di ottenere l'idea). È necessario creare la tabella temporanea manualmente. Ci vogliono circa 2 o 3 minuti per me fare - ancora troppo lungo per generare con ogni migrazione, ed è abbastanza statico comunque =)

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top