Skip to content

Ocak 7, 2011

9

MySQL IN Yerine JOIN Kullanarak Performans Artırmak

Apache mod_pagespeed

Merhaba arkadaşlar, bu yazımızda MySQL ‘de bir tablodaki verileri diğer tablo içinde ararken IN kullanmak yerine JOIN kullanarak sorgumuzu nasıl hızlandırabileceğimizi inceleyeceğiz.

MySQL ‘de bir tablodan veri alırken bazen bu verilerin ikinci tabloda da bulunması (IN) şartını ararız. Yani a ve b tablolarındaki kayıtlardan ortak olanları almak için (IN) kullanarak alt sorgu (subquery) oluştururuz.

Örnek Bir “IN” Sorgusu :

SELECT SQL_NO_CACHE COUNT(`pt1`.`id`)
FROM `pt1`
WHERE `id` IN ( SELECT `id` FROM `pt2` WHERE `id` > 50000 )

Sorgu Sonucu:

+-------------------+
| COUNT(`pt1`.`id`) |
+-------------------+
|            450000 |
+-------------------+
1 row in set (1 min 17.46 sec)

Bu sorgu bize pt2 tablosunda karşılığı olan kayıtları verir.  Ancak sorgu süresinden anlaşıldığı gibi biraz zaman alan bir sorgudur.

Çözüm: “IN” Yerine “JOIN” Kullanmak

Yukarıdaki sorguyla aynı sonucu veren sorgumuz aşağıdaki gibidir.

SELECT SQL_NO_CACHE COUNT(`pt1`.`id`)
FROM `pt1`, `pt2`
WHERE `pt1`.`id` = `pt2`.`id`
AND `pt2`.`id` > 50000

Sorgu Sonucu :

+-------------------+
| COUNT(`pt1`.`id`) |
+-------------------+
|            450000 |
+-------------------+
1 row in set (1.15 sec)

Sorgu sonucundan da anlaşılacağı gibi IN ‘e göre çok daha hızlı çalışan bir sorgu oldu.


Test Veritabanı Tablosu ve Datası Oluşturmak için Gerekli SQL

Aşağıdaki SQL komutları ile 2 adet tablo oluşturabilir ve 42 milyon kadar kayıt oluşturabilirsiniz. Dikkat edilmesi gereken şey sorguların bilgisayarınızı biraz zorlaması olacaktır. Bu işlemleri test ortamında yapmanızı öneririz.

# çalışacağımız veritabanını seçiyoruz
USE test;

# performans testi için tablo oluştur
CREATE TABLE IF NOT EXISTS pt1 (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
) Engine = MyISAM;

# tabloya veri ekle. sorgu sonrası toplam satır : 7
INSERT INTO pt1 VALUES (1), (2), (3), (4), (5), (6), (7);

# tabloya inner join ile veriler ekle. sorgu sonrası toplam satır: 350
INSERT INTO pt1 SELECT NULL FROM pt1 AS t1, pt1 AS t2, pt1 AS t3;

#sorgu sonrası toplam satır: 42.875.350
INSERT INTO pt1 SELECT NULL FROM pt1 AS t1, pt1 AS t2, pt1 AS t3; 

# performans testi için bir tablo daha oluştur
CREATE TABLE IF NOT EXISTS pt2 (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
) Engine = MyISAM;

# pt2 tablosuna 500.000 kayıt ekle.
INSERT INTO pt2 SELECT NULL FROM pt1 LIMIT 0, 500000;

Yazımızın sonuna geldiğimizde okuyucularına faydalı olacağını umuyoruz.

Toplam 9 Yorum Yorum Yaz
  1. sahan
    Tem 19 2011

    SQL_CACHE ne işe yarar ?

    Cevapla
  2. Tem 19 2011

    Yapılan SQL sorgusunun sonuçlarını önbelleğe (cache) atıp, daha sonra aynı sorgu çalıştırılması durumunda (önbellek silinmediyse) sorgu sonucunu önbellekten getirmesi suretiyle performans kazandıran bir özellik.

    SQL_NO_CACHE veya MySQL query caching seçeneğini devre dışı bırakarak sorgu sonucunun önbellekten değil direkt tablodan gelmesini sağlayabilirsiniz.

    Cevapla
  3. sahan
    Tem 22 2011

    anladım peki bu SQL_CACHE paremetresini eklemesede mysql önbellekde veri varsa önceliği ona vermezmi ?

    Cevapla
  4. Tem 22 2011

    Tekrar merbaba,

    Evet varsayılan ayarlarda SQL_CACHE yazmanıza gerek kalmadan MySQL bu işi kendisi yürütür.

    Cevapla
  5. engin
    Ara 1 2011

    burada kullanılan sorguları da bir yazıda açıklayabilir misiniz. kayıt sayısı nasıl oldu da milyonlara ulaştı :)

    Cevapla
    • Ara 1 2011

      Aslında sorgu basit çalışıyor;
      Önce tablo oluşturuyoruz,
      Daha sonra tabloya 7 adet kayıt ekliyoruz,
      Daha sonra 7 adet kaydı olan tabloyu 3 defa kendine join yapıyoruz (7^3 = 343),
      Böyle kendine joinleyerek devam ediyoruz ve milyon kaydımız oluyor.

      İhtiyaç duyuluyorsa konuyu başka bir yazıda SELECT INSERT kullanımı adı altında anlatabiliriz.

      Cevapla
  6. engin
    Ara 2 2011

    cevabınız için teşekkürler. aslında anlatırsanız fena olmaz. 5 yıldır php, mysql ile uğraşmama rağmen ilk defa karşılaşıyorum.

    Cevapla
  7. Kerim Ölmez
    Şub 10 2014

    Yazı size yardımcı oldu mu?
    Kesinlikle !
    Neden ?
    Aslında arama motorlarında arattığınızda, in veya join ne olursa genel olarak nasıl veri çekilir nasıl kullanılır kullanım amaçları ve sorguların yazım şekli ile karşılarşırsınız, bu makalede ise püf noktası olarak adlandırabileceğimiz pratik, küçük ama server side olarak baktığınızda çok önemli bir bilgi verilmiş.
    Teşekkürler Sayın KIRIMLI…

    Cevapla

Sizin fikriniz nedir? Lütfen aşağıdaki formu kullanarak yorum yapın.

(gerekli)
(gerekli)