Post Page Advertisement [Top]

Merhaba Sevgili Okurlar,
Bu yazımızda MSSQL dilini kullanarak yazdığımız sorguları nasıl daha hızlı çalışacak şekilde düzenleyebiliriz sorusuna cevap bulmaya çalışacağız.

Okurken ne dinlemeli ?


Bazen gerçekten bilmediğimiz bazen de öğrensek de aklımızda yer etmeyecek durumlar var. SQL performans işleri zaten karışımıza verimiz büyüdüğünde sorunlar çıkmaya başladığında başvurulan bir yol oluyor :)


Örneğin tarih karşılaştırması için sorgumuzun where koşulunda

WHERE  PROCESS_TIME =@FOX_DATE      
genellikle yukarıdaki şekilde karşılaştırma yaparız.Fakat aşağıdaki gibi bir karşılaştırma daha hızlı 
WHERE DATEADD(DAY, DATEDIFF(DAY, 0, PROCESS_TIME), 0) BETWEEN @FOX_DATE   AND @FOX_DATE + ' 23:59:59'

Bu ve bunun  gibi bir çok konuya değineceğiz,belki bir kaç yazı dizisi olabilir.

1.  Çalıştığımız veri sorgusuna bir veri limiti koyalım.
Örneğin SELECT * FROM Customers demek yerine eğer bizi kısıtlamıyorsa SELECT TOP 3 * FROM Customers
 demek daha doğru veya limit ve where koşulları ile sınırlandırmak gerek.

SELECT * FROM Customers
LIMIT 3SELECT * FROM Customers
WHERE ROWNUM <= 3

2. Sadece gerekli olan kolonları seçin

SELECT * FROM Customers yerine SELECT Name ,Surname,PhoneNumber FROM Customers gibi

3. Tabloyu oluşturan alanlarda optimum seçimi yapmak önemli string tipinde bir kolan açacaksak varchar kullanabiliriz 8000 karakterden fazla alan bekliyorsa iste o zaman text data tipi kullanalım. Eğer dili belli olan bir veri tabanımız var ise  ve dil içinde unicode karakterler içermiyor ise nvarchar yerine varchar kullanalım. nchar , nvarchar , char ve varchar'a kıyasla yaklaşık iki katı bellekte yer kaplar.
4.  Eğer anlık işlemler çok fazla olmayan bir tablo ise nolock kullanmak faydalı olacaktır. Tabloyu kilitlemeden veri çekebiliriz.Fakat bir  e-ticaret sitesi alım satım tablosu ise  belki de o saniyede yapılan bir alış verişi kaçırabiliriz nolock tavsiye edilmez.

SELECT 1 FROM LAZY_DOGS (NOLOCK) LZ WHERE

5.  Sub query'lerin yerine join kullanmalıyız.

SELECT a.id, (SELECT MAX(created) FROM posts
WHERE author_id = a.id) AS latest_post FROM authors

SELECT a.id, MAX(p.created) AS latest_post
FROM authors a
INNER JOIN posts p
ON (a.id = p.author_id)GROUP BY a.id


6.  Her sorgu çalıştırdığımızda SQL server kaç satır etkilendiğini altta gösterir. "29 rows affected" gibi ve buna bir zaman harcar .Store procedure 'larımızda en başa işimiz bittikten sonra SET NOCOUNT ON yazar isek  bu şekilde çalıştırırsak bu süreyi yok etmiş oluruz.

7.  UNION yerine mümkünse UNION ALL kullanabiliriz.
8.  SQL deadlocklardan kaçınmak için TRY -CATCH ve BEGIN TRANSACTION kullanalım.

Verimizin tutarlılığı açısından çok önemlidir. Hatalı kayıtlar bizi yanlış sonuçlara yönlendirebilir.Aynı ürünü iki kere satabiliriz :) Bu nedenle önemli sorguları Transaction levede yapmalı ve hata olduğunda rollback ile geri almalıyız. Böylece deadlock'lardan da kaçınmış oluruz.Aşağıdaki örnek kullanıma güzel bir örnek:

BEGIN TRANSACTIONBEGIN TRY  INSERT Authors VALUES  (@au_id, @au_lname, '', '', '', '', '', '11111', 0)  WAITFOR DELAY '00:00:05'  SELECT COUNT(*)  FROM Authors
  COMMITEND TRYBEGIN CATCH  SELECT ERROR_NUMBER() AS ErrorNumber  ROLLBACKEND CATCH;SELECT @@TRANCOUNT AS '@@Trancount'

9.  CURSOR yerine temp tablo ve while kullanmak.
Şayet döngü için kullanacağımız veri çok çok fazla değil ise cursor yerine temp tablo ve while yapısına çevirmek daha iyidir.

set nocount ondeclare @i int declare @sValue varchar(100)
set @i = 0
create table #tbl(ID int identity(1,1), Value varchar(100))
insert into #tbl(Value)select name
from master..sysdatabases (nolock)
while exists  (Select ID from #tbl a where a.ID > @i)beginselect @sValue = Value from #tbl where ID = @i
--begin tranprint 'My Value is ' + @sValue
--commit tran
set @i = @i + 1
end
drop table #tbl

10.  Hızlıdan yavaşa doğru kullanmamız gereken karşılaştırma operatörleri:
  • = (faster)
  • >, >=, <, <=
  • LIKE
  • <> (slower)
 Eğer LIKE kullanıyorsak wildcards dediğimiz karakterleri (% ,_  gibi) karşılaştırdığımız string karakterin sağına koymaya çalışmalıyız. Başına değil. SUBSTRING yerine ise LIKE kullanmak daha iyidir.
SELECT * FROM users WHERE name LIKE '%bar%'
SELECT * FROM users WHERE name LIKE 'bar%'

11.  WHERE cümceliklerini birbine bağlamak için kullandığımız AND 'lerde soldan sağa doğru okuma yapılır ve ilk koşulda false olabileceği yüksek düşündüğümüz koşulları ilk yazmalıyız böylece gereksiz yere diğer koşullar kontrol edilmez ilk koşulda false aldığı için diğer AND koşullarına bakmaz.

12.  OR yerine UNION kullanmak daha hızlı çalışır.
SELECT * FROM a, b WHERE a.p = b.q OR a.x = b.y

SELECT * FROM a, b WHERE a.p = b.q
UNIONSELECT * FROM a, b WHERE a.x = b.y

Sevgili Okurlar bu anlattıklarımı uygularken hepsini örnek veriniz üzerinde denemenizi tavsiye ederim. Bazı durumlarda sizin koşullarınızı tam bilmediğim için önerdiğim sorgu hızlandırma yöntemleri hızlı olmayabilir.Bunu en iyi deneyerek sürenin azalıp azalmadığını kontrol ederek bulabilirsiniz.

Bir sonraki yazım da SQL sorguları hızlandırma ile ilgili olacak, bir sonraki yazıda görüşmek üzere.

2 yorum:

Bottom Ad [Post Page]