2012-08-14 9 views

Respuesta

47

Rails tiene 2 formas de evitar el problema n + 1. Una implica crear una consulta basada en una gran combinación para obtener sus asociaciones, la otra implica hacer una consulta por asociación por separado.

Al hacer includes rieles decide qué estrategia utilizar para usted. Se establece de manera predeterminada en el enfoque de consulta por separado (precarga) a menos que crea que está utilizando las columnas de las asociaciones en sus condiciones u orden. Como eso solo funciona con el enfoque de uniones, lo usa en su lugar.

La heurística de Rails a veces se equivoca o puede tener una razón específica para preferir un enfoque sobre el otro. preload (y su método complementario eager_load) le permiten especificar qué estrategia quiere que utilicen los rieles.

+0

impresionante - una esquina oscura, indocumentado de ActiveRecord que uno. Gracias por brillar un poco de luz! – Phantomwhale

+3

Este blog discute el mismo tema http: //blog.bigbinary.com/2013/07/01/preload-vs-eager-load-vs-joins-vs-includes.html –

+2

Esta publicación de blog es muy útil y clara http://blog.arkency.com/2013/12/rails4- precarga / –

-3

Como apidoc dijo "Este método es obsoleto o se mueve en la última versión estable. La última versión existente (v3.0.9) se muestra aquí." Entonces, la diferencia es que incluye simplemente NO obsoleto.

+3

'obsoleto o movido'. En este caso, se mueve, no desaprovechado. Y ellos no son lo mismo. –

+0

Lo siento, pero si tengo la posibilidad de llamarlo (Rails 3.2.6) no se mueve para mí, simplemente desaprobado. – freeze

+2

apidoc recibe masivamente confundidos cuando la gente refactorizarán código de un módulo a otro - se puede pensar que un método se ha trasladado incluso a través de la API desde el punto de vista público no tiene –

0

Para una comprensión detallada refieren this blog.

en Pantalones cortos:

precarga carga la asociación de datos en una consulta separada.

User.preload(:posts).to_a 

# => SELECT "users".* FROM "users" SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (1) 

Incluye carga los datos de la asociación en una consulta independiente al igual que precarga. Sin embargo, es más inteligente que preload. Pero en algunos casos combina las consultas.

¿Cómo se incluye es más inteligente?

nosotros no se puede usar la tabla de publicaciones donde la condición. La siguiente consulta dará como resultado un error.

User.preload(:posts).where("posts.desc='ruby is awesome'") 

# => 
SQLite3::SQLException: no such column: posts.desc: 
SELECT "users".* FROM "users" WHERE (posts.desc='ruby is awesome') 

Pero podemos utilizar Cuadro de puestos en donde consulta con incluyen

User.includes(:posts).where('posts.desc = "ruby is awesome"').to_a 

# => 
SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "posts"."id" AS t1_r0, 
     "posts"."title" AS t1_r1, 
     "posts"."user_id" AS t1_r2, "posts"."desc" AS t1_r3 
FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id" 
WHERE (posts.desc = "ruby is awesome") 

Como se puede ver incluye interruptores de utilizar dos consultas separadas para crear una única combinación externa izquierda para obtener el datos. Y también aplicó la condición suministrada.

Cuestiones relacionadas