IN Operatörü ile ilgili Problemler

IN operatörünün genelde bilinmedi önemli performans problemi yaşatan problemini ele alacağız bugün.

Genelde yeni teknolojilerin getirdiği nimetlerden yararlanmayı çok severiz ve bu nimetlere güvenerek performanslı iş yapma yetimizi de yok etmeyide severiz aynı zamanda. Çünkü nasıl olsa SSD üzerinde DB lerimiz ya da Cache mekanizması yükseke storage da barındırılıyor Ram seviyemiz yüksek CPU desen sıkıntı yok istediğimiz Core a sahibiz felan diyerek ve source güven dayalı olarak code lamalarımzı yapar olduk. Bu yanlış bir durum olduğunu her defasında dile getiriyorum ve burada tekrar dile getirmek istedim.

Kullandığımız IN operatörünün bazı kıstasları var . Hemen bu konuyu örnek ile anlatmak istiyorum ,

Query 1 : ( Burada IN operatörüne 15 değer gönderiyorum)

SELECT
	SalesOrderID
   ,ProductID
   ,UnitPrice
FROM Sales.SalesOrderDetail
WHERE ModifiedDate
 IN (
 '2007-01-05', '2007-01-17', '2007-01-26', '2007-02-01', 
 '2007-02-04', '2007-02-14', '2007-02-28', '2007-03-06', 
 '2007-03-07', '2007-03-10', '2007-04-15', '2007-04-17', 
 '2007-08-08', '2007-11-11', '2007-12-25'
 )

Query 2 : ( Burada IN operatörüne 16 değer gönderiyorum…)

 -- 16
SELECT SalesOrderID, ProductID, UnitPrice
FROM Sales.SalesOrderDetail
WHERE ModifiedDate 
IN (
'2007-01-05', '2007-01-17', '2007-01-26', '2007-02-01', 
'2007-02-04', '2007-02-14', '2007-02-28', '2007-03-06',
'2007-03-07', '2007-03-10', '2007-04-15', '2007-04-17', 
'2007-08-08', '2007-11-11', '2007-12-25', '2007-12-26'
)

Şimdi ise bu iki query nin Execution Planlarına bakalım.

Normalde beklentimiz iki Execution Planıda aynı olması idi. Çünkü ikisinde de aynı query vardı sadece ikinci query de IN de ki değerlerimizi birincisine göre bir adet fazlaydı ama yukarıda ki Execution Plana baktığımızda bırakın planların aynı olmasını performans anlamında çok büyük fark olduğunu görmekteyiz.

I. Query nin Cost u {6189a1005e4f6dc613b8beb03d694ce50f0902974162d6a7dea944a970422cc9}39 iken , II. Query nin Cost u {6189a1005e4f6dc613b8beb03d694ce50f0902974162d6a7dea944a970422cc9}61 olarak görünmekte. İkinci sorgunun neredeyse birinci sorguya göre iki katı cost a sahip olduğunu ve ikinci sorguda ki bir tane ekstra değerin geç filtrelemeye sebep verdiğini execution plandan görmekteyiz.

Clustered Index Scan durumlarında bazı operatörlerde bu gibi kısıtlamalr ile karşılaşabilrisiniz. In operatörü için sadece 15 sınırı yok 64 te de bir sınır bulunmakta ve 65. değerde planı değiştirmektedir.

64 ve 65  adet değerler için incelememizi yapalım ,

Query 1 :  ( Burada IN operatörüne 64 değer gönderiyorum)

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
-- 64 
SELECT DISTINCT city
FROM Person.Address
WHERE city IN (
'Boulogne-Billancourt','Boulogne-sur-Mer','Bountiful','Bracknell','Bradenton','Braintree','Brampton','Branch','Branson','Braunschweig','Bremerton','Brisbane','Brossard','Burbank','Burien',
'Burlingame','Burnaby','Bury','Byron','Calgary','Caloundra','Camarillo','Cambridge','Campbellsville',
'Canoga Park','Carnation','Carol Stream','Carrollton','Carson','Casper','Cedar City','Cedar Park',
'Central Valley','Cergy','Cerritos','Chalk Riber','Chandler','Chantilly','Charlotte','Chatou',
'Cheektowaga','Chehalis','Cheltenham','Cheyenne','Chicago','Chula Vista','Cincinnati','Citrus Heights',
'City Of Commerce','Clackamas','Clarkston','Clay','Clearwater','Cliffside','Cloverdale','Coffs Harbour',
'College Station','Colma','Colombes','Colomiers','Columbus','Concord','Coronado','Corpus Christi'
)

Query 2 :  ( Burada IN operatörüne 65 değer gönderiyorum)

-- 65 
SELECT DISTINCT city
FROM Person.Address
WHERE city IN (
'Boulogne-Billancourt','Boulogne-sur-Mer','Bountiful','Bracknell','Bradenton','Braintree','Brampton','Branch','Branson','Braunschweig','Bremerton','Brisbane','Brossard','Burbank','Burien',
'Burlingame','Burnaby','Bury','Byron','Calgary','Caloundra','Camarillo','Cambridge','Campbellsville',
'Canoga Park','Carnation','Carol Stream','Carrollton','Carson','Casper','Cedar City','Cedar Park',
'Central Valley','Cergy','Cerritos','Chalk Riber','Chandler','Chantilly','Charlotte','Chatou',
'Cheektowaga','Chehalis','Cheltenham','Cheyenne','Chicago','Chula Vista','Cincinnati','Citrus Heights',
'City Of Commerce','Clackamas','Clarkston','Clay','Clearwater','Cliffside','Cloverdale','Coffs Harbour',
'College Station','Colma','Colombes','Colomiers','Columbus','Concord','Coronado','Corpus Christi','Seattle'
)

Execution Planlarını inceleyelim ,

Gördüğünüz üzere I. query de 64 adet , II. query de 65 adet ve query lerin execution planları farklı (aynı olmaıs gerekirken) ve  cost larına baktığında ikinci query costu aynı 15-16 örneğinde olduğu gibi daha yüksek I. query den.

Bu limitlere DBA ve Database Developer lar dikkat etmelidir.

Peki bu durumu nasıl aşarız sorusunu sorduğunuzu duyar gibiyim ?

Bu sorunu aşmanız için , IN ve NOt In bölümünde INNER JOIN kullanmanız harika olur. Örneğin kendi örneğimiz için INNER joinli method yaptığımızda aşağida ki gibi query hazırlamız yeterli olacaktır. Bu query diğer limitlerde sıkıtnı yaşadığınız query ler için daha performanslı olacaktır.

DECLARE @IN_Table TABLE (
	City NVARCHAR(60)
)
INSERT INTO @IN_Table
	VALUES ('Boulogne-Billancourt'), ('Boulogne-sur-Mer'), ('Bountiful'),
	('Bracknell'), ('Bradenton'), ('Braintree'), ('Brampton'),
	('Branch'), ('Branson'), ('Braunschweig'), ('Bremerton'),
	('Brisbane'), ('Brossard'), ('Burbank'), ('Burien'),
	('Burlingame'), ('Burnaby'), ('Bury'), ('Byron'), ('Calgary'),
	('Caloundra'), ('Camarillo'), ('Cambridge'), ('Campbellsville'),
	('Canoga Park'), ('Carnation'), ('Carol Stream'), ('Carrollton'),
	('Carson'), ('Casper'), ('Cedar City'), ('Cedar Park'),
	('Central Valley'), ('Cergy'), ('Cerritos'), ('Chalk Riber'),
	('Chandler'), ('Chantilly'), ('Charlotte'), ('Chatou'),
	('Cheektowaga'), ('Chehalis'), ('Cheltenham'), ('Cheyenne'),
	('Chicago'), ('Chula Vista'), ('Cincinnati'), ('Citrus Heights'),
	('City Of Commerce'), ('Clackamas'), ('Clarkston'), ('Clay'),
	('Clearwater'), ('Cliffside'), ('Cloverdale'), ('Coffs Harbour'),
	('College Station'), ('Colma'), ('Colombes'), ('Colomiers'),
	('Columbus'), ('Concord'), ('Coronado'), ('Corpus Christi'), ('Seattle')

SELECT DISTINCT
	a.City
FROM Person.Address a
INNER JOIN @IN_Table it
	ON (it.City = a.City)

 

IN ile Table versiyonunuda karşılaştırarak makalemizi sonlandırıyorum .

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
DECLARE @IN_Table TABLE (
	City NVARCHAR(60)
)
INSERT INTO @IN_Table
	VALUES ('Boulogne-Billancourt'), ('Boulogne-sur-Mer'), ('Bountiful'),
	('Bracknell'), ('Bradenton'), ('Braintree'), ('Brampton'),
	('Branch'), ('Branson'), ('Braunschweig'), ('Bremerton'),
	('Brisbane'), ('Brossard'), ('Burbank'), ('Burien'),
	('Burlingame'), ('Burnaby'), ('Bury'), ('Byron'), ('Calgary'),
	('Caloundra'), ('Camarillo'), ('Cambridge'), ('Campbellsville'),
	('Canoga Park'), ('Carnation'), ('Carol Stream'), ('Carrollton'),
	('Carson'), ('Casper'), ('Cedar City'), ('Cedar Park'),
	('Central Valley'), ('Cergy'), ('Cerritos'), ('Chalk Riber'),
	('Chandler'), ('Chantilly'), ('Charlotte'), ('Chatou'),
	('Cheektowaga'), ('Chehalis'), ('Cheltenham'), ('Cheyenne'),
	('Chicago'), ('Chula Vista'), ('Cincinnati'), ('Citrus Heights'),
	('City Of Commerce'), ('Clackamas'), ('Clarkston'), ('Clay'),
	('Clearwater'), ('Cliffside'), ('Cloverdale'), ('Coffs Harbour'),
	('College Station'), ('Colma'), ('Colombes'), ('Colomiers'),
	('Columbus'), ('Concord'), ('Coronado'), ('Corpus Christi'), ('Seattle')

SELECT DISTINCT
	a.City
FROM Person.Address a
INNER JOIN @IN_Table it
	ON (it.City = a.City)


	-- 65 
SELECT DISTINCT city
FROM Person.Address
WHERE city IN (
'Boulogne-Billancourt','Boulogne-sur-Mer','Bountiful','Bracknell','Bradenton','Braintree','Brampton','Branch','Branson','Braunschweig','Bremerton','Brisbane','Brossard','Burbank','Burien',
'Burlingame','Burnaby','Bury','Byron','Calgary','Caloundra','Camarillo','Cambridge','Campbellsville',
'Canoga Park','Carnation','Carol Stream','Carrollton','Carson','Casper','Cedar City','Cedar Park',
'Central Valley','Cergy','Cerritos','Chalk Riber','Chandler','Chantilly','Charlotte','Chatou',
'Cheektowaga','Chehalis','Cheltenham','Cheyenne','Chicago','Chula Vista','Cincinnati','Citrus Heights',
'City Of Commerce','Clackamas','Clarkston','Clay','Clearwater','Cliffside','Cloverdale','Coffs Harbour',
'College Station','Colma','Colombes','Colomiers','Columbus','Concord','Coronado','Corpus Christi'
)

 

 

 

Kolay Gelsin…

Leave a Reply

Your email address will not be published. Required fields are marked *