solomon resumen michael hoyer hawkins gratis editorial edición edicion consumidor coney comportamiento best 7ma 10ª ruby ruby-on-rails-3 database-migration

ruby - resumen - Rieles, ¿cómo migrar gran cantidad de datos?



hawkins best coney comportamiento del consumidor (5)

Tengo una aplicación de Rails 3 que ejecuta una versión anterior de Spree (un carrito de compras de código abierto). Estoy en el proceso de actualizarlo a la última versión. Esto requiere que ejecute numerosas migraciones en la base de datos para ser compatible con la última versión. Sin embargo, la base de datos actual de las aplicaciones es de aproximadamente 300 mb y la ejecución de las migraciones en mi máquina local (mac os x 10.7, ram de 4 gb, Core 2 Duo de 2.4GHz) tarda más de 3 días en completarse.

Pude reducir este tiempo a solo 16 horas utilizando una instancia de amazon ec2 (Instancias a pedido de alta E / S, cuadruple extra grande). Pero 16 horas aún no es suficiente, ya que tendré que retirar el sitio para realizar esta actualización.

¿Alguien tiene alguna otra sugerencia para bajar esta vez? ¿O algún consejo para aumentar el rendimiento de las migraciones?

FYI: utilizando ruby ​​1.9.2, y ubuntu en la instancia de amazon.


Desafortunadamente, la solución degradada es la única. Lo que es realmente lento en los rieles son los modelos activerecord. No son adecuados para tareas como esta.

Si quieres una migración rápida tendrás que hacerlo en sql.

Hay otro enfoque. Pero siempre tendrás que reescribir la mayoría de las migraciones ...



Esta respuesta tiene más que ver con el enfoque que con una solución técnica específica. Si su criterio principal es el tiempo de inactividad mínimo (y, por supuesto, la integridad de los datos), ¡la mejor estrategia para esto es no usar rieles!

En su lugar, puede hacer todo el trabajo pesado por adelantado y dejar solo la migración de datos "en tiempo real" crítica (estoy usando "migración" en el sentido de los no rieles aquí) como un paso durante la conmutación.

Así que tienes tu aplicación actual con su esquema de db y los datos de producción. Usted también (presumiblemente) tiene una versión de desarrollo de la aplicación basada en las gemas de la versión actualizada con el nuevo esquema de db pero sin datos. Todo lo que tienes que hacer es encontrar una manera de transformar los datos entre los dos. Esto se puede hacer de varias maneras, por ejemplo, utilizando SQL puro y tablas temporales cuando sea necesario o usando SQL y ruby ​​para generar instrucciones de inserción. Estos pasos se pueden dividir para que los datos que son bastante "estáticos" (tablas de referencia, productos, etc.) se puedan cargar en la db antes de tiempo y los datos que cambian con mayor frecuencia (usuarios, sesiones, pedidos, etc.) hecho durante el paso de migración.

Debe poder realizar un script de este procedimiento de exportación-transformación-importación para que sea repetible y tenga pruebas / verificaciones una vez que esté completo para garantizar la integridad de los datos. Si puede organizar el acceso a la nueva base de datos de producción durante la conmutación, debería ser fácil ejecutar el script en su contra. Si está restringido a un proceso de lanzamiento (por ejemplo, webistrano), es posible que tenga que encajarlo en una migración de rieles, pero puede ejecutar el SQL sin procesar mediante la ejecución.


Tal vez ya has considerado esto:

  1. Dígale al db que no se moleste en asegurarse de que todo esté en el disco (sin WAL, sin fsync, etc.), ahora tiene un db en memoria que debería marcar una gran diferencia. (Dado que ha desconectado la base de datos, puede restaurar desde una copia de seguridad en el improbable caso de pérdida de energía o similar). Encienda fsync / WAL cuando haya terminado.

  2. Es probable que pueda realizar algunas de las migraciones antes de desconectar la base de datos. Prueba esto en la puesta en escena, por supuesto. Esa gran migración de usuarios podría ser posible realizarla en vivo. Asegúrese de no hacerlo en una transacción, es posible que deba modificarlos un poco.

No estoy familiarizado con su situación exacta, pero estoy seguro de que hay muchas más cosas que puede hacer a menos que esto no sea suficiente.


  • Eliminar los índices de antemano y volver a agregarlos después es una buena idea.

  • También reemplazando .where (...). Cada uno con .find_each y tal vez agregar transacciones podría ayudar, como ya se mencionó.

  • Reemplace .save! con .save (: validate => false), debido a que durante las migraciones no obtiene entradas aleatorias de los usuarios, debería realizar actualizaciones en buen estado y las validaciones representan gran parte del tiempo de ejecución. O el uso de .update_attribute también omitirá las validaciones donde solo está actualizando un campo.

  • Donde sea posible, use menos objetos AR en un bucle. La creación de una instancia y luego la recolección de basura requiere tiempo de CPU y usa más memoria.