Key Lookup, query optimize ederken execution planlarda sık sık karşılaştığımız operatörlerden biridir.
Ne zaman oluşur?
SQL, bir sorgunun tamamını veya bir kısmını karşılamak için bir non-clustered index kullandığında oluşur, ancak bu index sorguya ait tüm bilgileri içermez bu sebeple eksik bilgilere ulaşabilmek için clustered index üzerinde arama işlemi yapılır.
İşte bir örnek;
SELECT BusinessEntityID,PersonType,FirstName,LastName FROM Person.Person WHERE FirstName=N’Roberto’
Key Lookup’a sebep olacak bir index atıyorum,
CREATE NONCLUSTERED INDEX [IX_Person_FirstName]
ON [Person].[Person] ([FirstName])
WITH (FILLFACTOR = 90)
Execution plan’da da görüleceği üzere, key loookup her zaman Nested Loops Join kullanmaktadır.
Çünkü her bir row için clustered index’e gidip nonclustered index’te olmayan bilgileri alması gerekiyor.
Peki bunu nasıl mı yapıyor?
Bunu yapabilmek için aslında create edilen bütün tablolarda var olan bir kolondan faydalanıyor. İşte o kolon ;
SELECT BusinessEntityID,PersonType,FirstName,LastName,%%lockres%%
FROM Person.Person
WHERE FirstName=N’Roberto’
Sorgunuza bu kolonu eklediğinizde clustered index’e sahip tablolarda sonuç kümesinde clustered index’in key’ini göreceksiniz. İşte Key Lookup operatörü bu bilgiden yararlanarak (her bir satır için clustered index’e giderek) diğer kolonlardaki bilgileri toplayabiliyor.
Buna göre, Number of executions (key lookup olduğunda) bilgisi bize aynı zamanda dönen row sayısı bilgisini de vermektedir. Bu durum parameter sniffing olan sorgularda acı verir.
Key Lookup operatörünü ortadan kaldırmak için Output List bölümündeki sütunları var olan index’imin include bölümüne eklemem yeterli olacaktır. (Tabii her zaman bu kadar basit olmayabilir.)
CREATE NONCLUSTERED INDEX [IX_Person_FirstName]
ON [Person].[Person]([FirstName])
INCLUDE ( [PersonType], [LastName]) WITH (FILLFACTOR = 90)
Index’imi düzenledikten sonra Key Lookup operatörü kalktı sadece non-clustered index üzerinden tüm bilgiler karşılanabildiği için bu index’i seek ederek, sonuçları döndürdü.
Sorgunun key lookup kullanırken ve düzelttikten sonraki istatistiksel okuma bilgilerini buraya koyuyorum.
set statistics io on
Bu basit bir örnekti ama bazen işler karmaşıklaşabilir.
— select * kullanımında (bunu sadece * olarak düşünmeyin, entity framework sorguları * yerine tüm sütun adlarını yazarak gönderiyor, eşdeğer sorgular diyebiliriz.)
Böyle durumlarda index’e bütün sütunları eklemek istemezsiniz bunun yerine öncelikle daha az sütun seçip seçemeyeceğinize karar vermek için sorgularınızı inceleyin.
Key Lookup her zaman kötü bir operatör değildir, bazı durumlarda olduğu şekilde bırakmanız gerekebilir. Bu sizin sorgunuza, index’lerinize ve tablo yapınıza göre değişiklik gösterecektir. Index’lerinizin include kısmını sütunlarla doldurmadan önce bunun maliyetini hesaplamanızı tavsiye ederim.
2 yorum