Sorgu Optimizasyonu (Query Optimization) – Sorgularımızı nasıl daha iyi hale getirebiliriz ?
Temel olarak SQL diline hakim olduğumuzda istediğimiz tablolardan istediğimiz verileri çekebilecek hale gelmiş oluyoruz. Aynı zamanda komut ve operatörlere daha fazla hakim olmaya başladığımızda farklı komutların aynı çıktıları bizlere verebileceğini de görmüş oluyoruz. Peki ya farklı komutların server tarafında yaptıkları işler tamamen aynı mı ? Hepsi aynı düzeyde mi performans veriyor ? Sunucuya gönderdiğimiz sorguları nasıl daha yüksek performanslı hale getirebiliriz ? Eğer sizlerin de bu tarz soruları varsa bu konuya biraz değinmenin vakti geldi.
SQL Sorgu Optimizasyonunun Amacı Nedir ?
SQL sorgu optimizasyonunun başlıca amaçları şunlardır ;
Yanıt Sürelerini Azaltmak : Amaç yanıt süresini azaltarak performansı arttırmaktır. Daha iyi bir kullanıcı deneyimi için kullanıcılara daha hızlı sonuçlar getirilmelidir.
Geliştirilmiş Verim : Gerekli tüm verileri getirmek için erişilecek kaynak sayısı en aza indirilmelidir. Belirli bir sorguda getirilecek satır sayısı, en az sayıda kaynak kullanılacak şekilde olmalıdır.
Sorgu performansını analiz etmeye yönelik metrikler nelerdir ?
Bu başlıkta performansımızı analiz ederken dikkat edeceğimiz unsurları ve ne anlama geldiklerini inceleyeceğiz.
1-) Execution Time : Sorgu performansını analiz etmek için en önemli ve ilk bakılacak metrik sorgunun yürütme süresidir. Execution Time, sorgunun satırları veritabanından döndürmek için geçirdiği süre olarak tanımlanır.
STATISTICS TIME ON
komutunu kullanarak sorgunun parse, compile, execution ve completion sürelerini görüntüleyebilirsiniz.
SET STATISTICS TIME ON
SELECT * FROM PERSON.PersonPhone;
Parse and Compile Time ( Ayrıştırma ve Derleme Süresi) : Sorgunun sözdizimini kontrol etmek için ve derlemek için geçen süreyi ifade eder.
Completion Time: Sorgunun sonucu döndürdüğü tam zamanı ifade eder.
Bu metrikleri analiz ederek sorgunun performansının analizini yapabilirsiniz.
2 – ) Statistics IO
IO, sorgu çalıştırıldığında okuma yapmak için arabelleklere erişir.
STATISTICS IO ON
komutunu kullanarak sorguyu yürütmek için gerçekleşen fiziksel (physical) ve mantıksal (logical) okumaların sayısını elde edebilirsiniz.
SET STATISTICS IO ON
SELECT * FROM PERSON.PersonPhone;
Logical Reads ( Mantıksal Okuma) : Arabellek önbelleğinde gerçekleştirilen okuma sayısı.
Physical Reads (Fiziksel Okuma) : Depolama aygıtında gerçekleştirilen okuma sayısı.
3 – ) Execution Plan
Execution Plan, bir sorgunun yürütülmesindeki ana aşamaları analiz etmenize yardımcı olur. Yürütmenin hangi bölümünün daha fazla zaman aldığını bulabilir ve o bölümü optimize edebilirsiniz.
Ayrıca sorgu yürütme sırasında gerçekleştirilen alt işlemler için daha ayrıntılı analiz görünümünü imlecinizi üzerine getirerek görebilirsiniz.
Sorgu Optimizasyon Teknikleri (Query Optimization Techniques)
Şimdiye kadar bir sorgunun nasıl yürütüldüğünü ve sorgu performasını nasıl analiz edebileceğimizi, nelerden yararlanabileceğimizi gördük. Şimdi sıra sorgu performansını nasıl optimize edeğimizi öğrenmekte.
İndeksleme (Indexing)
SQL Server’ da, bir sorgu çalıştırdığımızda bir yürütme planı oluşur. Yürütme planı bu bölümde eğer performansı optimize etmek için oluşturulabilecek herhangi bir indeks varsa uyarı verir. Bu uyarı ile mevcut tablonun hangi sütunlarının indekslenmesi gerektiği konusunda bilgi verir.
Yürütme planında Index Scan bölümüne sağ tıklayıp Missing Index Details… seçeneğine tıklarsanız açılan pencerede yorum satırlarını silerek kolayca indeks tanımlaması yapabilirsiniz.
Gerekli indeks tanımlamalarını yaptıktan sonra sunucu sorguların çıktılarını çok daha hızlı bir şekilde sizlere sunacaktır.
Seçim ( Selection)
Sorgulama yaparken kullanılan SELECT * ifadesiyle birlikte tüm veritabanı tarandığı için çok verimsizdir. Bunun yerine sütunlar belirtilirse çok daha yüksek performans ortaya çıkacaktır.
SET STATISTICS TIME ON
SELECT * FROM PERSON.PersonPhone
SET STATISTICS TIME ON
SELECT BusinessEntityID, PhoneNumber,PhoneNumberTypeID, ModifiedDate FROM PERSON.PersonPhone;
DISTINCT Kullanımından Kaçınma
SQL Server’ da DISTINCT komutu tekrar eden verileri sorgu sonucunda tekil olarak gösterir. Bu işlemi yapmak için ilgili satırları bir araya toplar ve sonra onları kaldırır. Fakat yapılan bu işlem performansı kötü etkilemektedir.
SET STATISTICS TIME ON
SELECT DISTINCT FirstName, LastName FROM Person.Person ;
SET STATISTICS TIME ON
SELECT FirstName, LastName FROM Person.Person ;
Örnekte görüldüğü üzere execution sürelerine bakarak DISTINCT komutunun performansı olumsuz etkilediğini söyleyebiliriz.
INNER JOIN ve WHERE kullanımları
Birden fazla tablodan veri çekmek istediğimizde WHERE komutu yerine INNER JOIN komutunu kullanarak çok daha yüksek performansa ulaşabilirsiniz.
SET STATISTICS TIME ON
SELECT A.FirstName, A.LastName, P.PhoneNumber FROM Person.Person AS A,
Person.PersonPhone AS P
WHERE P.BusinessEntityID = A.BusinessEntityID;
SET STATISTICS TIME ON
SELECT A.FirstName, A.LastName, P.PhoneNumber FROM Person.Person AS A
INNER JOIN Person.PersonPhone AS P
ON P.BusinessEntityID = A.BusinessEntityID;
Bu yazıda indeks çalışmasından ve bazı komut ve operatörlerin kullanım farklarından bahsettik. Bu yöntemleri kullanarak sorgu performasınızı çok daha iyi hale getirebilirsiniz. Sonraki yazılarda görüşmek üzere.