对查询的顺序会产生N + 1问题

时间:2016-11-02 22:14:27

标签: ruby-on-rails activerecord

我试图在ActiveRecord查询中解决N + 1问题。我想知道为什么order会产生N + 1问题。如果我删除它,它运作良好。看看这个:

效果正常

Rental.eager_load(:customer).limit(5).first.customer

SQL (1.7ms)  SELECT  "rentals"."id" AS t0_r0, "rentals"."customer_id" AS t0_r1, "rentals"."movie_id" AS t0_r2, "rentals"."created_at" AS t0_r3, "rentals"."updated_at" AS t0_r4, "customers"."id" AS t1_r0, "customers"."firstname" AS t1_r1, "customers"."lastname" AS t1_r2, "customers"."email" AS t1_r3, "customers"."stripe_id" AS t1_r4, "customers"."country" AS t1_r5, "customers"."city" AS t1_r6, "customers"."street_address" AS t1_r7, "customers"."zip_code" AS t1_r8, "customers"."state" AS t1_r9, "customers"."created_at" AS t1_r10, "customers"."updated_at" AS t1_r11, "customers"."encrypted_password" AS t1_r12, "customers"."reset_password_token" AS t1_r13, "customers"."reset_password_sent_at" AS t1_r14, "customers"."remember_created_at" AS t1_r15, "customers"."sign_in_count" AS t1_r16, "customers"."current_sign_in_at" AS t1_r17, "customers"."last_sign_in_at" AS t1_r18, "customers"."current_sign_in_ip" AS t1_r19, "customers"."last_sign_in_ip" AS t1_r20, "customers"."gender" AS t1_r21 FROM "rentals" LEFT OUTER JOIN "customers" ON "customers"."id" = "rentals"."customer_id" LIMIT 5
=> [#<Rental id: 7884, customer_id: 10001, movie_id: 756, created_at: "2013-10-16 08:45:50", updated_at: "2013-10-16 08:45:50">, #<Rental id: 8529, customer_id: 10001, movie_id: 870, created_at: "2014-03-24 05:22:13", updated_at: "2014-03-24 05:22:13">, #<Rental id: 12926, customer_id: 10001, movie_id: 805, created_at: "2014-11-26 07:00:47", updated_at: "2014-11-26 07:00:47">, #<Rental id: 7841, customer_id: 10002, movie_id: 480, created_at: "2016-01-15 02:55:03", updated_at: "2016-01-15 02:55:03">, #<Rental id: 13824, customer_id: 10002, movie_id: 537, created_at: "2013-08-12 12:46:25", updated_at: "2013-08-12 12:46:25">]

产生N + 1问题

现在,我只是在查询中添加.order(created_at: :desc)

Rental.eager_load(:customer).order(created_at: :desc).limit(5).each {|x| x.customer}

SQL (37.4ms)  SELECT  "rentals"."id" AS t0_r0, "rentals"."customer_id" AS t0_r1, "rentals"."movie_id" AS t0_r2, "rentals"."created_at" AS t0_r3, "rentals"."updated_at" AS t0_r4, "customers"."id" AS t1_r0, "customers"."firstname" AS t1_r1, "customers"."lastname" AS t1_r2, "customers"."email" AS t1_r3, "customers"."stripe_id" AS t1_r4, "customers"."country" AS t1_r5, "customers"."city" AS t1_r6, "customers"."street_address" AS t1_r7, "customers"."zip_code" AS t1_r8, "customers"."state" AS t1_r9, "customers"."created_at" AS t1_r10, "customers"."updated_at" AS t1_r11, "customers"."encrypted_password" AS t1_r12, "customers"."reset_password_token" AS t1_r13, "customers"."reset_password_sent_at" AS t1_r14, "customers"."remember_created_at" AS t1_r15, "customers"."sign_in_count" AS t1_r16, "customers"."current_sign_in_at" AS t1_r17, "customers"."last_sign_in_at" AS t1_r18, "customers"."current_sign_in_ip" AS t1_r19, "customers"."last_sign_in_ip" AS t1_r20, "customers"."gender" AS t1_r21 FROM "rentals" LEFT OUTER JOIN "customers" ON "customers"."id" = "rentals"."customer_id"  ORDER BY "rentals"."created_at" DESC LIMIT 5
  Customer Load (0.9ms)  SELECT  "customers".* FROM "customers"  WHERE "customers"."id" = $1 LIMIT 1  [["id", 20288]]
  Customer Load (0.7ms)  SELECT  "customers".* FROM "customers"  WHERE "customers"."id" = $1 LIMIT 1  [["id", 20288]]
  Customer Load (0.7ms)  SELECT  "customers".* FROM "customers"  WHERE "customers"."id" = $1 LIMIT 1  [["id", 20274]]
  Customer Load (0.7ms)  SELECT  "customers".* FROM "customers"  WHERE "customers"."id" = $1 LIMIT 1  [["id", 20284]]
=> [#<Rental id: 38836, customer_id: 20288, movie_id: 681, created_at: "2016-10-17 23:48:00", updated_at: "2016-10-17 23:48:00">, #<Rental id: 38833, customer_id: 20288, movie_id: 782, created_at: "2016-10-17 23:35:00", updated_at: "2016-10-17 23:35:00">, #<Rental id: 38767, customer_id: 20274, movie_id: 563, created_at: "2016-10-17 23:17:00", updated_at: "2016-10-17 23:17:00">, #<Rental id: 38664, customer_id: 20254, movie_id: 594, created_at: "2016-10-17 23:15:00", updated_at: "2016-10-17 23:15:00">, #<Rental id: 38815, customer_id: 20284, movie_id: 659, created_at: "2016-10-17 23:05:00", updated_at: "2016-10-17 23:05:00">]

我错过了什么吗?如何解决N + 1查询?

更新:

  • 如果我使用:asc而不是:desc排序,那么就没有N + 1问题。
  • 如果我在:id:asc的{​​{1}}等其他字段进行排序,那么就没有N + 1问题。

0 个答案:

没有答案