Rieles: rake db: migrate * * muy lento en Oracle
-
09-09-2019 - |
Pregunta
Estoy usando los carriles con el adaptador oracleenhanced
para crear una nueva interfaz para una aplicación antigua.
migraciones de bases de datos funcionan con éxito, pero tienen un tiempo increíblemente largo período de tiempo antes acabados rastrillo. Los cambios de bases de datos ocurren con bastante rapidez (1 ó 2 segundos), pero el vertedero db/schema.db
tarda más de una hora en completarse. (Véase el ejemplo la migración a continuación.)
Es un esquema relativamente grande (alrededor de 150 tablas), pero estoy seguro de que no debe tomar este tiempo para volcar cada descripción de la tabla.
¿Hay alguna forma de acelerar este proceso con sólo tomar la última schema.db
y aplicar el cambio especificado en la migración a ella? O soy capaz de saltarse este esquema volcado por completo?
Yo entiendo que esta schema.db
se utiliza para crear la base de datos de prueba desde cero cada vez, pero este caso, hay una gran parte de la lógica de la base de datos en la tabla de disparadores que no están incluidos en el schema.rb
de todos modos, por lo que las pruebas de desprendimiento hay bueno con nosotros en cualquier caso. (Eso es una cuestión totalmente diferente que tengo que resolver en algún otro momento.)
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
Solución
Después de todas las migraciones se aplican a la base de datos a continuación, el rastrillo db: migrate llamadas db: schema:. Tarea de volcado para generar el archivo schema.rb del esquema de base de datos actual
db: schema: método de "tablas" volcado de adaptador de llamada para obtener la lista de todas las tablas, a continuación, para cada tabla llama al método "índices" y el método "columnas". Puede encontrar instrucciones SELECT de SQL que se utilizan en estos métodos en el archivo oracle_enhanced_adapter.rb-activerecord oracle_enhanced-adaptador de joya. Básicamente lo hace desde selecciona TODAS% o diccionario de datos% USUARIO tablas para encontrar toda la información.
Al principio tuve problemas con el adaptador original de Oracle cuando lo usé con bases de datos con gran cantidad de diferentes esquemas (como el rendimiento puede verse afectado por el número total de tabla en la base de datos - no sólo en el esquema) y por lo tanto hice algunas optimizaciones en Oracle mejorado adaptador. Sería bueno averiguar qué métodos son lentos en su caso (sospecho que podría ser o bien "índices" o método de "columnas" que se ejecuta para cada tabla).
Una azada forma de depurar este problema sería si desea poner algunos mensajes de depuración en el archivo oracle_enhanced_adapter.rb por lo que se podía identificar qué llamadas a métodos están tomando tanto tiempo.
Otros consejos
Problema resuelto principalmente después de algún ronda de excavación en oracle_enhanced_adapter.rb
.
El problema se reducía a demasiadas tablas en el esquema local (muchas mesas EBA_%, EVT_%, EMP_%, SMP_%
se habían creado allí casualmente en algún momento), las tablas de archivos que se incluyen en el vertedero y un selecto de los diccionarios de datos que tienen 14 segundos para ejecutar .
Para fijar la velocidad, hice tres cosas:
- retiró todos los cuadros que no sean necesarios (alrededor de 250 de 500)
- tablas de archivos excluidos de la volcado esquema
- En caché el resultado de la consulta de larga ejecución
Esto mejoró el tiempo desde el vertedero de la migración / esquema para las 350 mesas restantes de unos 90 minutos a unos 15 segundos. Más de lo suficientemente rápido.
Mi código de la siguiente manera (en busca de inspiración no copiar y pegar - el código es bastante específica a mi base de datos, pero debe ser capaz de obtener la idea). Es necesario crear manualmente la tabla temporal. Se tarda unos 2 o 3 minutos para que haga - siendo demasiado largo para generar con cada migración, y es bastante estática de todos modos =)
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