Rails da Joins ve Includes Kullanımı

2017, Nov 22    

Includes ve Joins birbirine çok benzeyen iki Active Record methodudur. Her ikisi de çok kullanışlı metodlar olmasına karşılık yanlış kullanıldığında performansı azaltabilirler.

Includes ve Joins arasındaki fark?

Includes işlem yaparken eager loading kullanırken, joins lazy loading kullanır. Kısaca eager loading nesnenin ihtiyaç anından çok önce yaratılması ve daha sonra kullanmak için hazır halde bekletilmesidir. Bunun tam tersi olarak lazy loading ise nesnenin gerçekten ihtiyaç duyulacağı ana kadar alınmaması, bekletilmesi amacıyla kullanılır.

Ruby on Rails dokumantasyonunda includes için yapılan en önemli açıklama şudur;

“With includes, Active Record ensures that all of the specified associations are loaded using the minimum possible number of queries.””

Active Record includes ile belirtilen tüm ilişkilerin mümkün olan en az sayıda sorgu ile yüklenmesini sağlar.

Bir başka deyişle bir tabloyu ilişkili bir başka tabloyla sorgularken, her iki tablo da belleğe yüklenir ve bu da ilişkili verileri almak için gereken veritabanı sorgularının miktarını azaltır. Aşağıdaki kodda bütün şirketler(companies) ile ilişkili olan aktif(active) kişilerin(persons) listesini alıyoruz.

Burada eğer includes kullanmasaydık herbir şirkette çalışan herbir active kişinin adına ulaşmak için her seferinde ayrı bir veritabanı sorgusu atmak zorunda kalacaktık. Ancak includes kullandığımızda ilişkili person tablosu zaten yüklenmiş ve kullanıma hazır olduğu için tek sorgu ile alıp kullanabildik.

Peki ya bütün şirketlerdeki(companies) ilişkili kişi(person) kaydına ulaşmak fakat Person tablosundaki herhangi bir kaydı görüntülemek istemezsek ne olacak? Burada Person tablosundaki herbir kaydı yüklemek biraz anlamsız geliyor. İşte bu noktada Joins devreye giriyor.

Yukarıdaki örneği joins’e uyarlayalım.

includes ibaresinin yerini joins ile değiştirelim ve yanlıza company name’ e ulaşalım. Joins’in lazy load olduğundan daha önce bahsetmiştim. Burada joins ilişkili tabloyu kullanarak veritabanı sorgusunu gerçekleştirir ancak yanlızca Company table’ı memory’e yükler çünkü burada person tablosu gerekli değildir. Joins kullanarak gereksiz verileri gereksizce memory’e yüklemiyoruz. Eğer Person tablosunun verilerini daha sonra kullanmak istersek, daha fazla veritabanı sorgusu gerekecektir.

İkna olmadım bana istatistiklerle gel!

Aşağıdaki index action’ı anormal bir şekilde veritabanı sorguları üretiyordu.

Smithsonian Image

Burada gördüğünüz gibi tablonun her bir satırında, ilişkili diğer tablolara(zones, tiers) ulaşmak için iki adet sorgu atılıyor. Ölçeklendirildiğinde 265.2ms de bütün sorgular kaynaktan yükleniyor. Uygulamada performansı ve ölçeklenebilirliği koruyabilmek adına index action’ı includes ile tekrardan düzenleyebiliriz.

Bu düzenlemeyi yaptıktan sonra Active Record’un yüklenme süresi 2.8ms oldu. Ve sorgu sayısı yanlızca 5’e düştü. Bu da yüklenme süresinde %99’luk bir azalma demektir. Süpersonik değil mi ^^

Smithsonian Image

Kaynaklar
http://tomdallimore.com/

Anlatacaklarım burada bitti. Eğer yazıda bir hata ya da eksik olduğunu düşünüyorsan yorum olarak belirtmeni çok isterim.

Sevgiler