2013-04-06 12 views
5

Abbiamo molte "stored procedure di ricerca" che utilizzano più parametri Null per la ricerca di righe di dati in tabelle diverse. Sono di solito costruiti in questo modo:T-SQL - Viene utilizzato un piano non ottimale - la clausola WHERE deve essere cortocircuitata

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) 

Questo può andare avanti per un massimo di 30-40 parametri e quello che abbiamo notato è, anche se è previsto solo parametro1, il piano di esecuzione passa attraverso scansioni indice dell'altra tabelle che possono rallentare significativamente la query (pochi secondi). I test ci mostrano che mantenere solo la prima riga dall'istruzione WHERE rende istantanea la query.

  1. ho letto che shortcuiting non è possibile, ma sono là aggirare o modi di costruire le query che sarebbe forse essere più efficace?

  2. Attualmente aggiriamo questo problema avendo versioni diverse dello stesso SELECT/FROM/JOINS ma con diversi set di parametri nella clausola WHERE e in base a quali parametri vengono passati, scegliamo la corretta istruzione select da seguire. Questo è lungo, disordinato e difficile da mantenere.

+3

Avete considerato l'utilizzo di [SQL dinamico] (http://www.sommarskog.se/dynamic_sql.html)? Anche con l'avvertenza [SQL Injection] (http://en.wikipedia.org/wiki/SQL_injection) potrebbe essere più adatto alle tue esigenze. – Oded

+0

La conversione dinamica parametrizzata di sql e sql non è un problema – StrayCatDBA

+0

Daremo un'occhiata di nuovo a SQL dinamico, ma sembra tornare a come eravamo soliti fare e costruire complesse stringhe di codice SQL all'interno delle applicazioni stesse con una serie di condizioni che rendevano quasi impossibile comprendere la query a una rapida occhiata. C'è anche un modo per mantenere l'evidenziazione della sintassi/gli strumenti all'interno di SQL Management Studio per quelle query? – FrancoisCN

risposta

4

I piani di query in SQL Server vengono compilati e archiviati per il riutilizzo. Anche se SQL Server rileva che i parametri sono null, deve elaborare un piano di query che funzioni per i casi in cui sono not null.

Query accenno option (recompile) è stata introdotta in SQL Server 2005, ma non è stato fino SQL Server 2008 che in realtà ha avuto un effetto sul tipo di interrogazione che avete qui.

Quando la query viene ricompilata ogni volta che non verrà memorizzata nella cache del piano di query, SQL Server è libero di ottimizzare i controlli rispetto ai parametri null.

Per saperne di più su di esso qui Dynamic Search Conditions in T-SQL

Alcuni codice di esempio è possibile verificare per vedere la differenza di piani di query. La prima chiamata all'SP eseguirà una ricerca dell'indice e la seconda eseguirà una scansione dell'indice cluster.

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

Ho usato questo approccio con grande successo. Gli unici problemi che ho riscontrato sono quando il numero di compilazioni diventa un problema. Dopodiché, sql con parametri dinamici è l'unica opzione reale. – StrayCatDBA

+0

Cosa intendi per numero di compilazioni diventa un problema? – FrancoisCN

+0

@FrancoisCN La compilazione della query richiede risorse (CPU) sul server e l'utilizzo di "opzione (ricompilare)" significa che la query verrà compilata per ogni esecuzione. Quindi utilizzarlo potrebbe mettere a dura prova il tuo server. Quanto è grande l'impatto dipende dalla complessità della query e dalla frequenza con cui viene eseguita. –