• 04-02-2015, 16:41:16
    #1
    Merhaba arkadaşlar,
    Gördüğüm kadarıyla hiç araştırma yapmadan bodoslama dalıyoruz kod yazmaya. Nasıl daha iyi kod yazarım nasıl daha iyi verim alırım demiyoruz. O yüzden mysql kullanırken en iyi yolları anlatma gereği duydum. Başlayalım.

    1. Mysql yerine Mysqli kullanın.
    Mysqli ile sunulan en dikkat çekici yenilikler şu şekildedir;
    - Nesne Tabanlı Arabirim
    - Ön Hazırlıklı Sorgular
    ikisi arasında karşılaştırmaları;
    http://kodogren.org/2014/mysql-vs-my...rsilastirmasi/
    http://kodogren.org/2014/mysql-vs-mysqli-fonksiyonlari/
    ya da google da arama yaparak görebilirsiniz.

    2. Kodlarınızı en iyi şekilde optimize edin.
    Çoğu Mysql server ında cache leme açıktır. Ama hangi sorgular direk cache e alınır hangisi alınmaz ona dikkat etmemiz gerekir.
    Örnek;
    // cache e alınmaz
    $r = mysqli_query("SELECT ad FROM kullanici WHERE tarih >= CURDATE()");
     
    // cache e alınır
    $bugun = date("Y-m-d");
    $r = mysqli_query("SELECT ad FROM kullanici WHERE tarih >= '$bugun'");
    ilk sorgu cache e alınmaz sebebi ise Mysql fonksiyonlarından curdate i kullanmamız. ama aynı işlemi yapan 2. sorguda ise cache alınır bir daha ki sorgulamada Mysql daha hızlı cevap verir.
    CURDATE(), NOW(), RAND() gibi fonksiyonlar Mysql in cacheleme özelliğini kullanamamanıza neden olur.

    3. Anahtar(key) kullanın.
    --ogrenci--
    ad --- soyad --- bolum
    gibi bir tablonuz varsa primary key ekleyin.
    --ogrenci--
    id --- ad --- soyad --- bolum

    buradaki id primary key olarak eklenmiştir. daha sonra işlem yapmak istediğimizde bu primary key e göre çok rahatlıkla işlem yapabiliriz.
    UPDATE, SELECT .... WHERE id = id_degeri
    şeklinde işlemlerimiz çok daha basit ve hızlı şekilde çözülecektir.

    4. Tek cevap gelecek sorgularda LIMIT 1 kullanın.
    Veritabanında aynı kullanıcı adıyla ya da aynı mail adresiyle kayıt yapılmasını çoğumuz engelleriz zaten. peki bu kontrolü yaparken nasıl sorgu yapmamız lazım. Zaten o isimde ya da o mail adresiyle tek sorgu gelecek biliyoruz. O yüzden daha iyi performans için LIMIT 1 ekleyin.
    // bunun yerine:
    $r = mysqli_query("SELECT id FROM kullanici WHERE ad = '$ad'");
    
    // bunu kullanın
    $r = mysqli_query("SELECT id FROM kullanici WHERE ad = '$ad' LIMIT 1");
    5. Arama yapılacak alanlarda FullText ya da Index(KEY) kullanın.
    Aşağıdaki resimde key kullanmadan önce yapılan sorguyla key eklendikten sonraki süreler karşılaştırılmış.

    ALTER TABLE 'users' ADD INDEX ('last_name');
    ALTER TABLE `users` ADD FULLTEXT `fulltextindex` (`last_name`).
    Benim tavsiyem fulltext kullanmanız yönündedir.
    FullText hakkında daha fazla bilgi almak için google da arama yapabilirsiniz. ya da bu linke bakabilirsiniz.

    6. JOIN işlemlerinde doğru seçimi yapın
    Bildiğimiz üzere JOIN işlemi yapmanın 3 farklı yolu var. Bunlar arasından hangisini seçeceğimize dikkat etmemiz lazım. Görüyorum ki herkes LEFT JOIN kullanıyor ama ya işlemlerinizde INNER JOIN daha basit ve daha hızlı olacaksa hiç araştırdınız mı?

    LEFT JOIN

    RIGHT JOIN

    INNER JOIN


    3ü arasındaki farkları ve örnekleri bu linklerden görebilirsiniz.
    http://www.w3schools.com/sql/sql_join_left.asp
    http://www.w3schools.com/sql/sql_join_right.asp
    http://www.w3schools.com/sql/sql_join_inner.asp

    7. JOIN işlemlerinde aynı tipleri eşleştirin
    $r = mysqli_query("SELECT ad FROM kullanici
        LEFT JOIN sirket ON (kullanici.il_id = sirket.il_id)
        WHERE kullanici.id = $user_id");
    burada kullanici tablosuyla sirket tablosunu birleştirdik fakat önemli olan konu kullanici tablosundaki il_id INT olup sirket tablosundaki il_id nin FLOAT ya da VARCHAR gibi farklı tiplerde olmamasına dikkat edin.

    8. RAND() kullanmaktan kaçının
    Sorgularınızda RAND() kullanmak daha çok işinize geliyor biliyorum ama bunun yerine kesinlikle ve kesinlikle php ile random yapmayı deneyin göreceksiniz ki daha hızlı sonuç alacaksınız.

    // sakın!!
    $r = mysqli_query("SELECT ad FROM kullanici ORDER BY RAND() LIMIT 1");
    
    // onun yerine bunu kullanın
    $r = mysqli_query("SELECT count(id) as sayi FROM kullanici");
    $d = mysqli_fetch_row($r);
    $rand = mt_rand(0,$d['sayi'] - 1);
     
    $r = mysqli_query("SELECT ad FROM kullanici LIMIT $rand, 1");
    Benim tavsiyem hiç random kullanmama yönünde ama illa kullanacaksanız böyle kullanın.

    9. num_rows kullanmaktan kaçının
    Sorgularınızda num_rows kullanmak daha çok işinize geliyor biliyorum ama bunun yerine kesinlikle ve kesinlikle COUNT(id) yapmayı deneyin göreceksiniz ki daha hızlı sonuç alacaksınız.

    // sakın!!
    $r = mysqli_query("SELECT ad FROM kullanici WHERE il = '$il'");
    echo mysqli_num_rows($r);
    
    // onun yerine bunu kullanın
    $r = mysqli_query("SELECT COUNT(id) as sayi FROM kullanici WHERE il = '$il'");
    $d = mysqli_fetch_row($r);
    echo $d['sayi'];
    10. SELECT * kullanmaktan kaçının
    Sorgu sırasında almak istediğiniz veriler net olsun. kullanıcının adını mı alıcam sadece adını alın. ad, soyad, bolum, il lazımsa sadece bunları alın.

    // yapmayın
    $r = mysqli_query("SELECT * FROM kullanici WHERE id = 1");
    $d = mysqli_fetch_assoc($r);
    echo 'Hoşgeldiniz '.$d['ad'];
     
    // bunu kullanın
    $r = mysqli_query("SELECT ad FROM kullanici WHERE id = 1");
    $d = mysqli_fetch_assoc($r);
    echo 'Hoşgeldiniz '.$d['ad'];
    11. Primary Key kullanın
    Her tablonuzda bir tane primary key olsun çekinmeyin. Tabi primary key kullanırken dikkat etmemiz lazım VARCHAR ya da FLOAT gibi saçma primary keyler belirlemeyin. INT kullanmak her zaman primary keyler için daha iyidir.

    id = INT, PRIMARY KEY, AUTO_INCREMENT
    hatta UNSIGNED da kullanabilirsiniz negatif değer alamayacak nasılsa.

    12. NULL dan kaçının
    Çok zor da olmadıkça veritabanlarında NULL değerleri alacak tablo oluşturmaktan kaçının.

    Eğer INT ise alan default olarak NULL yerine 0 tanımlayın.
    VARCHAR ise default olarak '' tanımlayın.

    13. Alanlarınız sabit uzunlukta ve yeterince olsun
    Oluşturduğunuz alanlar sabit uzunlukta ve yeterli derecede olsun.

    Örneğin sadece 0,1 değeri alacak bi yer için gidipte INT(11) gibi saçma alanlar oluşturmayın. BIT(1) ya da TINYINT(1) yeterli olacaktır.

    Text alanlarından mümkünse uzak durun bunun yerine VARCHAR(1024) gibi ne kadar lazımsa o kadar tanımlama yapın.

    ip alanlarını tutan alan için gidipte VARCHAR(255) falan kullanmayın, VARCHAR(15) yeterli olacaktır.

    14. Büyük sayılarda INSERT ya da DELETE işlemi yapmayın
    Sorguları parçalamayı deneyin.
    // bunun yerine
    mysqli_query("DELETE FROM logs WHERE log_date <= '2009-10-01'");
    
    // bunu kullanın
    while (1) {
    	$r = mysqli_query("SELECT COUNT(id) as sayi FROM logs WHERE log_date <= '2009-10-01'");
    	$d = mysqli_fetch_row($r);
    	
    	if ($d['sayi'] > 0)
    		mysqli_query("DELETE FROM logs WHERE log_date <= '2009-10-01' LIMIT 1000");
        else break;
    	
        // az bekle
        usleep(50000);
    }
    15. Depolama Motorlarını(Storage Engine) doğru kullanın
    MyISAM ve InnoDB her ikisininde kendine göre avantajları ya da dezavantajları var. bunları tablonuza göre uygun olup olmadığını kontrol ederek seçiniz.

    Eğerki InnoDB kullanmaya karar verdiyseniz burası çok önemli innodb_buffer_pool_size alanını kendinize göre arttırın ya da hostunuza iletin o geri dönüş yapacaktır.
    innodb_buffer_pool_size = 256M
    Hepsini okuduğunuz için Teşekkür ederim.
    Kolay gelsin.

    NOT: Konudaki linklerin benimle uzaktan yakından alakası olmayıp konuyu daha iyi kavrayabilmeniz için örnek olarak verilmiştir.
    Ayrıca hatalı olduğumu düşünüyorsanız konu altından nedeni ile açıklarsanız ben de bilgilenmiş olurum. Şimdiden teşekkür ederim.
  • 21-11-2015, 22:35:52
    #2
    oldukça yararlı bir döküman olmuş. teşekkürler.
  • 22-11-2015, 10:44:17
    #3
    deleter20 adlı üyeden alıntı: mesajı görüntüle
    12. NULL dan kaçının
    Çok zor da olmadıkça veritabanlarında NULL değerleri alacak tablo oluşturmaktan kaçının.

    Eğer INT ise alan default olarak NULL yerine 0 tanımlayın.
    VARCHAR ise default olarak '' tanımlayın.

    13. Alanlarınız sabit uzunlukta ve yeterince olsun
    Oluşturduğunuz alanlar sabit uzunlukta ve yeterli derecede olsun.

    Örneğin sadece 0,1 değeri alacak bi yer için gidipte INT(11) ya da INT(25) gibi saçma alanlar oluşturmayın. BIT(1) ya da TINYINT(1) yeterli olacaktır.

    Text alanlarından mümkünse uzak durun bunun yerine VARCHAR(1024) gibi ne kadar lazımsa o kadar tanımlama yapın.

    ip alanlarını tutan alan için gidipte VARCHAR(255) falan kullanmayın, VARCHAR(15) yeterli olacaktır.
    Kolonun Null olmasının bir sakıncası yoktur. 0 değeri atamak ya da kolona varsayılan olarak boş metin koymak doğru bir yakşalım değildir. Null o kolonda değer olmadığını gösterir. Bu önemli bir göstergedir ve null da indexlenir. Dummy veri atamak hem yanlış hem de saçmadır. Yani null kullanın.

    Tamsayı kolon tanımlaması yazarken parantez içerisinde yazacağınız değer o kolonun boyutuna ilişkin değil sunumuna ilişkin bir işarettir, zero-fill kullanmazsanız onu da fark edemezsiniz. Yani int(1) ile int(11) arasında temel olarak hiçbir fark yoktur. Boyuta ilişkin belirlemeler yapmak istediğinizde tinyint,int,bigint tanımlamalarını kullanmanız gerekir.
  • 22-11-2015, 11:06:23
    #4
    13. maddede haklısın zaten anlatmak istediğim şeyle senin söylediğin şey arasında bir fark yok. 13. madde düzenlenmiştir.

    12. maddeye gelirsek bunu tüm dünya tartışıyor google'da ya da stackoverflow.com gibi sitelerde tartışmaları açıkça görebilirsiniz zaten. sadece mysql için değil çoğu veritabanı için bu tartışmalar devam ediyor. ben kendi hız testime göre değerlendirmemi yaptım. dediğim gibi hala tartışılan bir konu olduğu için belki de sen haklısın
  • 22-11-2015, 20:25:06
    #5
    güzel çalışma
  • 22-11-2015, 20:55:59
    #6
    yarar bilgiler iyi paylaşım
  • 27-01-2016, 13:56:16
    #7
    eline sağlık hocam 10 numarı bi anlatım olmuş