2013-04-06 20 views
5

Farklı tablolardaki veri satırlarını aramak için birden çok null parametresi alan çok sayıda "arama saklı yordam" var. Genellikle bu gibi inşa ediyoruz:T-SQL - En uygun olmayan plan kullanılır - WHERE yan tümcesi kısa dönemli olmalıdır

SELECT  * 
FROM  Table1 T1 
INNER JOIN Table2 T2 
    ON  T2.something = T1.something 
WHERE  (@parameter1 IS NULL OR T1.Column1 = @parameter1) 
     AND (@parameter2 IS NULL OR T2.Column2 = @parameter2) 
     AND (@parameter3 IS NULL OR T1.Column3 LIKE '%' + @parameter3 + '%') 
     AND (@parameter4 IS NULL OR T2.Column4 LIKE '%' + @parameter4 + '%')  
     AND (@parameter5 IS NULL OR T1.Column5 = @parameter5) 

Bu kadar 30-40 parametreler için gitmek ve ne fark ettik sadece parametre1 sunulmuş olsa bile olduğunu edebilir, yürütme planı diğer dizin taramaları geçer sorguyu yavaşlatan tablolar (birkaç saniye). Testler bize WHERE ifadesinden sadece ilk satırı tutmanın sorguyu anında yaptıklarını gösterir.

  1. ben shortcuiting mümkün olmadığını okudum ama muhtemelen daha verimli olacaktır sorguları oluşturmak için yollar var geçici veya duyuyoruz?

  2. Şu anda bu soruna, aynı SELECT/FROM/JOINS'in farklı sürümlerine sahip olmakla birlikte, ancak WHERE yan tümcesinde farklı parametreler kümesiyle çalışıyoruz ve hangi parametrelerin geçtiğine bağlı olarak, içinden geçmek için uygun select deyimini seçiyoruz. Bu uzun, dağınık ve korumak zor.

+3

[dynamic SQL] (http://www.sommarskog.se/dynamic_sql.html) kullanmayı düşündünüz mü? [SQL Injection] (http://en.wikipedia.org/wiki/SQL_injection) uyarısı ile bile ihtiyaçlarınız için daha uygun olabilir. – Oded

+0

Yapılandırılmış dinamik sql ve sql enjeksiyonu oluşturma bir sorun değil – StrayCatDBA

+0

Dinamik sql'de yeniden bir bakacağız, ancak yalnızca bir şeyleri nasıl yaptığımıza ve SQL kodunun karmaşık dizelerini, uygulamaların kendileriyle nasıl oluşturduğumuza döneceğiz. Hızlı bir bakışta sorguyu anlamak neredeyse imkansız hale getiren koşulların bir demet. Ayrıca, SQL sorgu stüdyosunda sözdizimi vurgulama/araçlarını bu sorgular için tutmanın bir yolu var mı? – FrancoisCN

cevap

4

SQL Server'daki sorgu planları derlenip yeniden kullanılmak üzere depolanır. SQL Server, parametrelerinizin null olduğunu görse bile, not null oldukları durumlar için çalışacak bir sorgu planıyla gelmelidir.

Sorgu ipucu option (recompile) SQL Server 2005'te kullanıma sunuldu, ancak SQL Server 2008'in gerçekte burada sahip olduğunuz sorgu türünde bir etkisi olduğu ortaya çıkana kadar değildi.

Sorgu, her zaman sorgu planı önbelleğinde depolanmayacak şekilde derlendiğinde, SQL Server, denetimleri null olan parametrelere göre en iyi duruma getirmek için ücretsizdir.

burada Dynamic Search Conditions in T-SQL

sorgu planlarında farkı görmek için test edebileceğiniz bazı örnek kodlar bu konuda daha fazla bilgi. SP'ye ilk çağrı bir indeks araması yapacak ve ikincisi kümelenmiş bir indeks taraması yapacaktır.

create table T 
(
    ID int identity primary key, 
    Col1 int, 
    Col2 int 
); 

go 

create index IX_T on T(Col1); 

go 

create procedure GetT 
    @Col1 int, 
    @Col2 int 
as 

select ID 
from T 
where (Col1 = @Col1 or @Col1 is null) and 
     (Col2 = @Col2 or @Col2 is null) 
option (recompile); 

go 

exec GetT 1, null 
exec GetT 1, 1 
+1

Bu yaklaşımı büyük başarı için kullandım. Derlemelerin sayısı bir sorun olduğunda, sahip olduğum tek sorunlar. Bundan sonra, dinamik parametreli sql tek gerçek seçenektir. – StrayCatDBA

+0

Derleme sayısıyla ne demek oluyor? – FrancoisCN

+0

@FrancoisCN Sorguyu derleme sunucuya kaynakları (CPU) alır ve 'option (recompile)' kullanarak, her bir yürütme için sorgunun derleneceği anlamına gelir. Bu nedenle, sunucunuza bir yük getirebilir. Etki ne kadar büyük olursa, sorgunun karmaşıklığına ve ne sıklıkla yürütüldüğüne bağlıdır. –

İlgili konular