2015-06-29 13 views
5

içerir olduğu gibi belleğe tüm ilişkili kayıtları yük:ActiveRecord kullanım performansı için katılır ama yanılmışsam sürece

  • joins bir inner join
  • includes nedenleri nedenleri: joins çünkü veritabanı seviyesinde includes daha iyi performansa sahiptir bir subquery

Ve genel olarak, bir inner join birdaha hızlıdır.

Örnek:

#app/models/owner.rb 
class Owner < ActiveRecord::Base 
    has_many :pets 
end 

#app/models/pet.rb 
class Pet < ActiveRecord::Base 
    belongs_to :owner 
end 

rails console kullanma: neredeyse her zaman daha iyi olurdu gibi

Yani
irb(main):001:0> @owners = Owner.all.joins(:pets) 
Owner Load (0.3ms) SELECT "owners".* FROM "owners" INNER JOIN "pets" ON "pets"."owner_id" = "owners"."id" 

görünüşe:

# showing how 'includes' in rails causes an IN statement which is a subquery 
irb(main):001:0> @owners = Owner.all.includes(:pets) 
Owner Load (2.7ms) SELECT "owners".* FROM "owners" 
Pet Load (0.4ms) SELECT "pets".* FROM "pets" WHERE "pets"."owner_id" IN (1, 2, 3) 

Ve şimdi joins kullanarak hangi bir inner join neden olurüzerinden joins kullanın Çünkü:

  • includes bir subquery (IN deyimi) neden olur
  • joins genellikle alt sorgu Ancak

daha hızlı bir inner join neden olur joins kullanarak bir yakaladım yoktur. This article does a great job describing it. Temel olarak, includes tüm ilişkili nesneleri belleğe yükler, böylece ilişkili nesnelerin özelliklerinden herhangi birini sorgularsanız, veritabanına vurmaz. Bu arada, joins, ilişkili nesnelerin özniteliklerine bellek yükler, bu nedenle, özniteliklerden herhangi birini sorgularsanız, veritabanında ek isabetler yapar.

İşte benim sorum: Performans için joins gibi iç birleştirme yapmak mümkün ama aynı zamanda tüm ilişkili nesneleri includes gibi belleğe yüklemek mümkün mü?
Başka bir deyişle: tüm ilişkili nesneleri includes gibi belleğe yüklemek mümkün mü, ancak bir alt sorgunun aksine bir iç birleştirmeye neden olur?

cevap

6

JOIN'un her zaman iki sorgudan daha hızlı olduğu varsayımının doğru olmadığını düşünüyorum. Veritabanı tablolarınızın boyutuna bağlıdır.

Veritabanınızda binlerce sahip ve evcil hayvan olduğunu düşünün. Daha sonra, sadece 10 kayıt yüklemek isteyip istemediğiniz halde, veritabanınız önce bir arada olmak zorundaydı. Öte yandan, bu 10 sahip için tüm evcil hayvanları yüklemek için 10 sahip ve bir sorgu yükleme bir sorgu JOIN daha hızlı olacaktır.

Ben iki yöntem de farklı sorunları çözmek için var olduğunu iddia ediyorum:

  • joins kullanılır her iki tablo verileri bir sorgu çalıştırmak için iki tablo birleştirmek gerektiğinde.N + 1 sorgularından kaçınmak için
  • includes kullanılır.

Btw:

Bu genellikle basit katılmak için yapılmış bir performans iyileştirme neden olacaktır: Rails documentationincludesjoins fazla performans faydası vardır bir not vardır.