Öncelikle yanıt veripte yardımcı olacak arkadaşlara şimdiden teşekkür ederim...
2 sene önce bir firma için yaptığım bir intranet sistemi var ve şu ana kadar sorunsuz çalışıyor sadece bu 2 senede çıkan bazı eksiklikler tespit ettik bunları da üzerine eklemek yerine sıfırdan bir alt yapı ile yapalım daha temiz olur diye düşündük, bu noktada size sormak istediğim bir performans sorusu var...
Şu anda ki mysql yapısı alttaki gibi;
Müşteriler -> 7.000 Kayıt
Sözleşmeler -> 24.000 Kayıt
Taksitler -> 180.000 Kayıt
Cari İşlemler -> 450.000 Kayıt
Gördüğünüz gibi 2 senede ciddi bir kayıt oluştu ve bu oran giderek artacak... Bu firmanın esasen 2 ana ürünü var ben tablo yapısını alttaki gibi yapsam;
A_tipi_Sözleşmeler
B_tipi_Sözleşmeler
A_tipi_Taksitler
B_tipi_Taksitler
Diğer_Taksitler
A_tipi_Cari İşlemler
B_tipi_Cari İşlemler
Diğer_Cari İşlemler
ve bu sayede kayıtları daha az satırlar olarak 3'er alt tabloya bölmüş olsam bunun bana performans açısından bir faydası olur mu, olursa da ciddi anlamda mı olur yoksa o kadar az olur ki uğraşmaya bile gerek yok mu dersiniz?
Bir de bu tablolardan bazen öyle raporlar alınıyor ki sorgu süresi bile 2dk'yı bulduğu oluyor; Örn. 7k müşterinin tamamının sözleşme detayları onların alt taksitleri ve o taksitlere yapılan ödemelerin detayları ve bu detaylara bağlı olarak hesaplanan ödeme performansı gibi, böyle durumlarda mecburen veriyi inner join ile alıp birleştirmem gerekecek...
Siz tahminen ne demek istediğimi 3 aşağı 5 yukarı anlamışsınızdır, sizce performans açısından bu yukarıda anlattığım şekilde tabloları 3'er parçaya bölüp gerektiğinde inner join ile almak mantıklı mı yoksa hiç bulaşma böyle teker tablo daha mı mantıklı performans açısından? Soruya cevap verirken kayıt sayısının önümüzdeki 2-3 yılda bazı tablolarda 1-1.5 milyon civarına çıkacağını da hesaba katarsanız çok sevinirim...
Performans Sorusu
5
●483
- 15-01-2016, 22:12:52Performans artışını sorgularını düzelterek çözüme kavuşturabilirsin.slayer1ss adlı üyeden alıntı: mesajı görüntüle
Yani Veritabanında bir tablodaki verilerin hepsi gerekli değilse. sadece gerekli olan alanları sınırlandırarak sorgularını bu şekilde azaltmalısın,
A tipi B tibi taksitlerin türünü farklı tabloda tutuyorsan
Örneğin :
TaksitTipi
ID :
TaksitTipAdı
şeklinde
bu tarz aynı verileri aynı veritabanında barındırıyorsanda bunları tek tabloya toparlamanı ve id değeri vermeni öneririm veritabanındaki verileri şişirmenin pek bi anlamı yok bu konuda,
İhtiyacına göre detaylı bi şekilde tablonun analiz edilmesi gerekiyor. projeyi göz önüne alıp bakılmadan sadece bunları söyleyebilirim.
Ama temel kural sorgulardaki gereksiz kullanmadığın verileri getirtmemek. - 15-01-2016, 23:25:21PrivateTR adlı üyeden alıntı: mesajı görüntüle
Dediğim gibi şu anda tüm taksitler aynı veritabanındaki tek bir tabloda, cari işlemler ve sözleşmeler de aynı şekilde kendilerine ait tablolarda duruyorlar sadece merak ettiğim acaba bunları tiplerine göre farklı tablolara almak günlük kullanımda bu şekilde farklı tablolarda sorgulamak ama rapor içinde inner join ile hepsini birleştirip sonuçları basmak acaba daha fazla performans sağlar mı sağlamaz mı...
Biraz daha detaya inmek gerekirse...
Tablo yapısı alttaki şekilde ve tüm id alanları primary key olarak auto increment ve unique olarak tanımlı
sozlesmeler id => 'ID No', ad => 'Ad', musteri => 'Müşteri ID No', islemtarihi => 'Sözleşme Tarihi', islem => 'Sözleşme Tipi', apid => 'Ürün', tip => 'Ürün Tipi', tutar => 'Tutar' taksitler id => 'ID No', sozlesme => 'Sözleşme ID No', musteri => 'Müşteri ID No', tarih => 'İşlem Tarihi', vade => 'Vade Tarihi', borc => 'Borç Bakiyesi', alacak => 'Alınan Bakiye', kalan => 'Kalan Bakiye' cariislemler id NOT NULL, taksit => 'Taksit No', musteri => 'Müşteri ID No', tarih => 'İşlem Tarihi', islem => 'İşlem Tipi', tutar => 'Tutar', onay => 'Onay Durumu', onaylayan => 'Onaylayan', onaytarihi => 'Onay Tarihi', odeme => 'Ödeme Şekli', hesap => 'Banka Hesabı'
Olabilecek en basit bir standart rapor sorgusu ise alttaki şekilde ama bu dediğim gibi en basit sorgulardan birisi diğerleri biraz daha kompleks olanları var...
select s.ad,s.islemtarihi,s.islem,t.vade,t.borc,t.alacak,t.kalan,m.ad,m.tcno from taksitler as t left join sozlesmeler as s on s.id=t.sozlesme left join musteriler as m on m.id=t.musteri where s.alici!='0' and s.sozlesmetipi='0' and s.islem='Kira' and t.durum='0' and s.durum='0' and s.tip='P' and t.vade>=1452636000 and t.vade<=1452895199 and t.kalan>0 order by t.vade .
Şimdi konunun özetine tekrar gelirsek; şu anda tüm veriler kendilerine ait tekil tablolardalar ve normalization mantığında gidiyorum ki böylesi kullanım açısından bana daha mantıklı geliyor ancak yarın öbür gün bu tablolardaki kayıtlar milyonlara ulaştığında
1- Sistemdeki kullanıcılardan birisi bir müşterinin hesabını açıpta sözleşmelerini sorguladığında milyon tane kayıt olan tek bir tabloda mı sorgu yapmak daha hızlı olur yoksa 500.000'er tane kayıt olan a_tipi_sözleşmeler/b_tipi_sözleşmeler şeklinde 2 farklı tabloda mı yapmak daha hızlı olur
2- 500.000'er 2 tablo yap böl derseniz de örnek verdiğim sorgudaki gibi bir rapor almak istediğimde önce inner join ile a_tipi_sözleşmeler/b_tipi_sözleşmeler tablolarını vs birleştirmem gerekecek, bu performans açısından +/- ne gibi bir durum oluşturur? - 16-01-2016, 00:03:43Inner Join ile View oluşturulması şart zaten,slayer1ss adlı üyeden alıntı: mesajı görüntüle
Her yıl içerisinde geçmiş yıllara ait verilerin sürekli bir ihtiyacı yok ise geçmiş yılların verilerinide sorgu içerisine almazsın ama bunları belli periyotlarda sorgulatıp raporunu geçici bir tabloda tutarsın ve rapor listeleteceğinde bu tablodaki alınmış toplam değerleri verirsin böylelikle her seferinde veritabanına gidip sorguyu çekmez ama güncelleme işlemide yanına koyarsın 1 kere bu işlem güncellenir sistematik olarak ve güncellenen veriden gelen rapor ayrı bir tabloda tuttuğunda hiçbir problem olmaz.
Özetle,
Örneğin 2015 yıl içerisindeki raporlarını alıp bir tabloda tutarsın.
2014
2013 için bu şekilde gider,
bulunan yıl içerisinde sürekli görmek isteniyorsa genel rapor. bunuda belirli periyotlarda güncelleme talimatı verilir. sorun hallolur
Amaç kısaca sql server'e her seferinde yüklü select sorgusu göndermemek.
İhtiyaç olan bilgide değişimin güncellemenin ne zaman yapıldığı tespit edilirse buna göre şekillendirirsin hocam. - 16-01-2016, 18:37:23Böyle bölmek mantıklı değil. Öncelikle mysqlden kurtulman gerek. Mysql yerine MariaDB 10 kur. Sonra Tokudb diye bi eklentisi var onun onu aktifleştir. Ve tablolarının yapısını MYISAM yada InnoDB olanları TokuDB ye çevir.slayer1ss adlı üyeden alıntı: mesajı görüntüle
Where cümlesinde kullandığın alanlara index oluştur. 20 Milyon kayıt çeker tablo.
Daha olmadı hareket tablosunu partition table ile böle. Partition table tek tablo gibi görünür. Fakat 20 dosya bölersin. tablo %5000 hızlanır.
Önemli olan bir şey daha joinli sorgularda ve where deki alanlara index açmak.
Örnek A tablosunda where urunid=5 and renk=2 gibi bir sorgun var ise; buna özgü index açıp urunid ve renk kolonlarını eklersen sorgu süresi %800 düşer. - 16-01-2016, 19:16:46xTROxTRO adlı üyeden alıntı: mesajı görüntüle
Teşekkür ederim cevabınız için, oldukça detaylı şekilde açıklamışsınız sizin ve üstteki arkadaşın yaptığı yorumlardan yola çıkarak kafamda ne yapacağım iyice şekillendi...
Bu arada Mysql dediğime bakmayın bende MariaDB kurucam zaten ama tokudb eklentisinden haberim yoktu onu iyice bir araştırıcam... Bir de partition table ile böl 20 dosyaya bölersin demişsiniz ya burada disk i/o etkisi olur mu?
Edit:
Tokudb için deminden beri biraz araştırma yapıyorum da "The TokuDB storage engine is for use in high-performance and write-intensive environments, offering increased compression and better performance." demişler ancak bu sistemde yazma olayı o kadar çok çok çok aktif olan bir durum değil, sizce bu gerçekten gerekli mi? Bunu sorma sebebim bu sistemin ayrıca mysql replication ile ayrı bir sunucuya yedeklemesi var ve o sunucu da biraz eski olduğu için mariadb kurulu değil sadece ana sunucunun çökmesi durumunda kullanıldığı için o sunucuda güncelleme yapmakla da esasında uğraşmak istemiyorum onun için merak ettim, eğer mutlaka kur sadece yazmada değil okumada da çok faydasını göreceksin derseniz diğer sunucuyu da toptan silip sıfırdan temiz bir şekilde kurucam...