Question

J'utilise des rails avec l'adaptateur oracleenhanced pour créer une nouvelle interface pour une application héritée.

migrations de bases de données fonctionnent avec succès, mais prennent une quantité incroyablement longue de temps avant que les finitions de râteau. Les changements de base de données se produisent assez rapidement (1 ou 2 secondes), mais la décharge de db/schema.db prend plus d'une heure. (Voir par exemple la migration ci-dessous.)

Il est un schéma relativement important (environ 150 tables), mais je suis sûr qu'il ne devrait pas prendre longtemps pour vider chaque description de la table.

Y at-il de toute façon à accélérer ce en prenant simplement la dernière schema.db et l'application du changement prévu dans la migration vers elle? Ou suis-je capable de sauter cette décharge de schéma tout à fait?

Je comprends ce schema.db est utilisé pour créer la base de données de test à partir de zéro à chaque fois, mais ce cas, il y a une grande partie de la logique de base de données dans le tableau des déclencheurs qui ne sont pas inclus dans le schema.rb de toute façon, les tests de rake sont pas bon pour nous dans tous les cas. (C'est une question tout à fait différent que je dois régler à un autre point.)

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
Était-ce utile?

La solution

Après toutes les migrations sont appliquées à la base de données puis rake db: migrate appels db: schéma:. Tâche de vidage pour générer un fichier à partir schema.rb schéma de base de données actuelle

db: schéma: vidage adaptateur méthode « tables » de l'appel pour obtenir la liste de toutes les tables, puis pour chaque table appelle méthode « index » et méthode « colonnes ». Vous pouvez trouver des instructions SQL SELECT qui sont utilisés dans ces méthodes dans le fichier oracle_enhanced_adapter.rb de gemme activerecord-oracle_enhanced-adaptateur. Fondamentalement, il ne choisit de tOUs% ou USER% tableaux de données du dictionnaire pour trouver toutes les informations.

Dans un premier temps, j'ai eu des problèmes avec l'original adaptateur Oracle lorsque je l'ai utilisé avec des bases de données avec beaucoup de schémas différents (comme la performance peut être affectée par le nombre total de table dans la base de données - non seulement dans votre schéma) et donc je l'ai fait quelques optimisations Oracle amélioré adaptateur. Il serait bon de savoir quelles méthodes sont lentes dans votre cas (je pense que cela pourrait être soit la méthode « index » ou « colonnes » qui est exécutée pour chaque table).

Une houe façon de déboguer cette question serait si vous mettriez des messages de débogage dans le fichier oracle_enhanced_adapter.rb afin que vous puissiez identifier les appels de méthode prennent si longtemps.

Autres conseils

Problème résolu la plupart du temps après un certain tour de creuser dans oracle_enhanced_adapter.rb.

Le problème est descendu à beaucoup trop de tables dans le schéma local (de nombreuses tables de EBA_%, EVT_%, EMP_%, SMP_% avaient été créés là coïncidente à un moment donné), des tables d'archivage étant inclus dans la décharge et une sélection des dictionnaires de données prenant 14 secondes pour exécuter .

Pour fixer la vitesse, je l'ai fait trois choses:

  1. Laissé tomber toutes les tables non nécessaires (environ 250 sur 500)
  2. tables d'archives exclues de la décharge de schéma
  3. Cached le résultat de la requête d'exécution longue

a amélioré le temps de la décharge migration / de schéma pour les 350 tables restantes d'environ 90 minutes à environ 15 secondes. Plus qu'assez vite.

Mon code comme suit (pour l'inspiration ne pas copier et coller - ce code est assez spécifique à ma base de données, mais vous devriez être en mesure d'obtenir l'idée). Vous devez créer la table temporaire manuellement. Il faut environ 2 ou 3 minutes pour moi de faire - encore trop long pour générer à chaque migration, et il est assez statique quand même =)

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top