2009-06-26 10 views
17

Per i miei query SQL, Io di solito il seguente per le istruzioni SELECT:T-SQL 1 = 1 Performance Hit

SELECT ... 
FROM table t 
WHERE 1=1 
    AND t.[column1] = @param1 
    AND t.[column2] = @param2 

questo modo sarà più facile se ho bisogno di aggiungere/rimuovere/commentare eventuali clausole WHERE, dal momento che non devo preoccuparmi della prima linea.

C'è qualche colpo di prestazioni quando si utilizza questo modello?

Informazione supplementare:

Esempio per sheepsimulator e tutti gli altri che non hanno ottenuto l'utilizzo.

Supponiamo che la query di cui sopra, ho bisogno di cambiare @ param1 da non incluso nella query:

Con 1 = 1:

... 
WHERE 1=1 <-- no change 
    --AND t.[column1] = @param1 <-- changed 
    AND t.[column2] = @param2 <-- no change 
... 

Senza 1 = 1:

... 
WHERE <-- no change 
    --t.[column1] = @param1 <-- changed 
    {AND removed} t.[column2] = @param2 <-- changed 
... 
+1

Mi dispiace se sembra un po 'daff, ma non sono davvero sicuro di come aggiungere 1 = 1 alla tua clausola WHERE ti porti i benefici di cui sopra; potresti approfondire questo argomento per quelli di noi che vorrebbero imparare questa possibile migliore pratica? –

+0

@sheepsimulator: è super facile commentare e decommentare qualsiasi condizione semplicemente anticipandolo con doppio trattino (-) – Quassnoi

+2

Hey Adrian, faccio sempre la stessa cosa, è così comodo compilare query dinamiche ... – tekBlues

risposta

11

È probabile che se si utilizza il profiler e si guardi, si finirà col vedere che l'ottimizzatore finirà per ignorarlo più spesso, quindi nel grande schema delle cose, probabilmente non ci sarà molto in performanc e guadagno o perdite.

+1

Sono d'accordo. @ Adrian- se scrivi le due query insieme e attiva il piano di esecuzione, probabilmente vedrai che entrambe le query sono del 50% ciascuna. – RichardOD

1

Nessuna perdita di prestazioni. Anche se la tua clausola WHERE è caricata con un gran numero di confronti, questo è piccolo.

Il caso migliore è che si tratta di un confronto bit-a-bit. Il caso peggiore è che le cifre sono valutate come numeri interi.

17

No, SQL Server è abbastanza intelligente da omettere questa condizione dal piano di esecuzione poiché è sempre TRUE.

Lo stesso vale per Oracle, MySQL e PostgreSQL.

+0

Hai una fonte per questo? Ti credo, collegherei solo qualcosa a cui fare riferimento. –

+0

@Danny: per MySQL, sì: http://dev.mysql.com/doc/refman/5.6/en/where-optimizations.html * Rimozione costante delle condizioni (necessaria a causa del piegamento costante) *, per altri no ma costante la piegatura è la caratteristica principale di qualsiasi ottimizzatore – Quassnoi

1

Per domande di qualsiasi ragionevole complessità non ci saranno differenze. Puoi guardare alcuni piani di esecuzione e anche confrontare i costi di esecuzione reali e vedere di persona.

2

Non c'è alcuna differenza, in quanto hanno valutato le costanti e sono ottimizzate. Io uso sia 1 = 1 che 0 = 1 in entrambe le liste di numeri AND e OR generati a mano e nel codice e non ha alcun effetto.

3

Questo non ha alcun impatto sulle prestazioni, ma il testo SQL sembra essere stato storpiato da un attacco di SQL injection. Il trucco "1 = 1" appare in molti attacchi basati su SQL injection. Corri solo il rischio che un tuo cliente un giorno disponga di una "scatola nera" che monitora il traffico SQL e troverai la tua app contrassegnata come "hackerata". Anche gli analizzatori di codice sorgente potrebbero segnalarlo. È un colpo lungo, certo, ma qualcosa che vale la pena mettere in bilico.

+0

Un trucco interessante, ma questo è un punto valido. Potrei iniziare a utilizzarlo durante lo sviluppo, ma vorrei eliminarlo prima di rilasciarlo in produzione. –

+5

Non è un punto valido, direi. L'iniezione SQL utilizza "OR 1 = 1" non "1 = 1 AND". Questi due sono distintamente diversi, se un'app non può differenziarli, sei sicuro che gli altri risultati sono affidabili? –

+0

Se si esegue questa operazione su un'app Web o un sistema SAAS, il cliente probabilmente non è in grado di installare i propri strumenti di monitoraggio. E ovviamente se installi il tuo, sai che queste domande sono sicure. – danielson317

2

Poiché la condizione è sempre true, SQL Server la ignorerà. È possibile verificare eseguendo due query, una con la condizione e una senza, e confrontando i due piani di esecuzione effettivi.

Un'alternativa per raggiungere la vostra facilità di commentare requisito è quello di ristrutturare la vostra richiesta:

 
SELECT ... 
FROM table t 
WHERE 
    t.[column1] = @param1 AND 
    t.[column2] = @param2 AND 
    t.[column3] = @param3 

È quindi possibile aggiungere/rimuovere/commentare le linee nelle condizioni in cui e sarà ancora SQL valida.

+1

L'aggiunta di una linea richiede la modifica dell'ultima riga. –

+2

sì ... a meno che non lo si aggiunga come ultima riga :) – adrianbanks

0

un impatto potenzialmente leggermente negativo di questo è che il AND 1=1 si fermerà impianto di SQL Server simple parameterisation da calci in.

Demo sceneggiatura

DBCC FREEPROCCACHE; /*<-- Don't run on production box!*/ 

CREATE TABLE [E7ED0174-9820-4B29-BCDF-C999CA319131] 
(
X INT, 
Y INT, 
PRIMARY KEY (X,Y) 
); 

GO 
SELECT * 
FROM [E7ED0174-9820-4B29-BCDF-C999CA319131] 
WHERE X = 1 
     AND Y = 2; 
GO 
SELECT * 
FROM [E7ED0174-9820-4B29-BCDF-C999CA319131] 
WHERE X = 2 
     AND Y = 3; 
GO 
SELECT * 
FROM [E7ED0174-9820-4B29-BCDF-C999CA319131] 
WHERE 1 = 1 
     AND X = 1 
     AND Y = 2 
GO 
SELECT * 
FROM [E7ED0174-9820-4B29-BCDF-C999CA319131] 
WHERE 1 = 1 
     AND X = 2 
     AND Y = 3  

SELECT usecounts, 
     execution_count, 
     size_in_bytes, 
     cacheobjtype, 
     objtype, 
     text, 
     creation_time, 
     last_execution_time, 
     execution_count 
FROM sys.dm_exec_cached_plans a 
     INNER JOIN sys.dm_exec_query_stats b 
     ON a.plan_handle = b.plan_handle 
     CROSS apply sys.dm_exec_sql_text(b.sql_handle) AS sql_text 
WHERE text LIKE '%\[E7ED0174-9820-4B29-BCDF-C999CA319131\]%' ESCAPE '\' 
     AND text NOT LIKE '%this_query%' 
ORDER BY last_execution_time DESC  

GO 

DROP TABLE [E7ED0174-9820-4B29-BCDF-C999CA319131] 

mostra che sia le query senza il 1=1 era soddisfatto da una singola versione parametrizzata del piano memorizzato nella cache mentre le query con lo 1=1 ha compilato e memorizzato un piano separato per i diversi valori costanti.

enter image description here

Idealmente non dovrebbe essere affidamento su questo in ogni caso se e dovrebbe essere esplicitamente parametrizzazione query per assicurare che gli elementi desiderati sono parametrizzati ei parametri sono i tipi di dati corretti.

Problemi correlati