desarrollamos comunidades y redes sociales verticales

Emergia-on-rails2
Emergia-on-rails1
Blog de Emergia On Rails

Inserción múltiple de registros: SQLs INSERT SELECT en Rails

0
Publicado por Fernan2 el 21 de Junio de 2012

Un problema típico de cualquier aplicación, sea Rails o no (o sea web o no), es el querer hacer una copia de un bloque de datos a otro sitio, con algún pequeño cambio y/o filtrado. Por ejemplo, puedo querer copiar los banners de la sección de depositos a una tabla de banners activos...

Un enfoque "de programador novato", pero que también puede verse en libros de programación de nivel básico, es hacerlo con un bucle:

  for ad in Ad.where(section: 'depositos')
    ActiveAd.create(title: ad.title, image_active: ad.image, url_active: ad.url)
  end

Pero si te miras los logs (algo que siempre debe hacerse), verás que este enfoque genera una SQL de INSERT por cada registro (más una para el SELECT):

  SELECT * FROM ads WHERE title = 'depositos'
  INSERT INTO active_ads (title, image_active, url_active) VALUES ('728x90 sup', 'http://images.example.org/728-dep.jpg', '/shop')
  INSERT INTO active_ads (title, image_active, url_active) VALUES ('468x60 med', 'http://images.example.org/468-dep.jpg', '/shop')
  INSERT INTO active_ads (title, image_active, url_active) VALUES ('300x250 lat', 'http://images.example.org/300-dep.jpg', '/shop')

Si el número de registros es pequeño, no pasará nada; si es mediano, el tiempo de respuesta empeorará ligeramente, y los logs se ensuciarán bastante y dejarán de ser útiles (lo cual en sí ya es un daño no despreciable)... y si el número de registros es grande, el impacto de esto hará que rendimiento del servidor se vea perjudicado, afectando también a páginas que no tengan nada que ver con este código, y entraremos en la dinámica del "Rails no escala"...

Obviamente, el problema no es que Rails no escala, sino que las cosas no deben hacerse así. Hay una instrucción SQL capaz de hacer esto en un solo paso, y es la que debe usarse:

  INSERT INTO active_ads (title, image_active, url_active) SELECT title, image, url FROM ads WHERE ads.section = 'depositos'

Este es uno de los pocos casos para los que ActiveRecord no nos da "de fábrica" una sintaxis elegante y railera para escribir la consulta. No todo está perdido: si lo usas con cierta frecuencia, la gema ar-extensions te permite hacer esto:

  ActiveAd.insert_select(
    into: [:title, :image_active, :url_active],
    select: [:title, :image, :url],
    from: :ads,
    conditions: ['section = ?', 'depositos'],
  )

Pero si es para un uso puntual, quizá no valga la pena añadir una gema al proyecto sólo para limpiar unas pocas consultas... Si este es el caso, la opción es lanzar la SQL directamente:

  sql = "INSERT INTO active_ads (title, image_active, url_active) SELECT title, image, url FROM ads WHERE ads.section = 'depositos'"
  ActiveRecord::Base.connection.execute(sql)

No nos engañemos: esto no es la panacea, insertar muchos registros nunca va a ser una tarea ligera para el servidor. Pero al menos, habremos optimizado el rendimiento en una zona crítica, y además dejaremos de ensuciar los logs, y por si fuera poco la query aparecerá en el log de consultas lentas de MySQL y podremos detectar más fácilmente los problemas para tratar de optimizarlos.

Comparte este artículo

compartir Compartir Inserción múltiple de registros: SQLs INSERT SELECT en Rails en Twitter Compartir Inserción múltiple de registros: SQLs INSERT SELECT en Rails en Menéame Compartir Inserción múltiple de registros: SQLs INSERT SELECT en Rails en Negóciame Compartir Inserción múltiple de registros: SQLs INSERT SELECT en Rails en Facebook Compartir Inserción múltiple de registros: SQLs INSERT SELECT en Rails en del.icio.us Compartir Inserción múltiple de registros: SQLs INSERT SELECT en Rails en Google Buzz
 Recomendado: -
Etiquetas: optimización de rendimiento · SQL · Rails no escala



Añadir comentario
0
Comentarios



Inserción múltiple de registros: SQLs INSERT SELECT en Rails




Síguenos en Twitter @EmergiaRails

 

actualidad

empleo

¿Quieres trabajar con nosotros?
Déjanos tus datos si quieres formar parte de nuestra empresa


Ver ofertas


síguenos

Facebook de Emergia Twitter de Emergia


suscríbete

Si deseas recibir información sobre novedades de emergia