Buono, cattivo o indifferente: DOVE 1 = 1


14

Data questa domanda su reddit, ho ripulito la query per sottolineare dove si trovava il problema nella query. Uso prima la virgola e WHERE 1=1per semplificare la modifica delle query, quindi le mie query generalmente finiscono in questo modo:

SELECT 
     C.CompanyName
    ,O.ShippedDate
    ,OD.UnitPrice
    ,P.ProductName
FROM 
               Customers       as C
    INNER JOIN Orders          as O  ON C.CustomerID = O.CustomerID
    INNER JOIN [Order Details] as OD ON O.OrderID    = OD.OrderID
    INNER JOIN Products        as P  ON P.ProductID  = OD.ProductID
Where 1=1
--  AND O.ShippedDate Between '4/1/2008' And '4/30/2008'
    And P.productname = 'TOFU'
Order By C.CompanyName

Qualcuno ha sostanzialmente affermato che 1 = 1 è generalmente pigro e cattivo per le prestazioni .

Dato che non voglio "ottimizzare prematuramente", voglio seguire le buone pratiche. Ho già esaminato i piani di query in precedenza, ma in generale solo per scoprire quali indici posso aggiungere (o modificare) per rendere più veloci le mie query.

La domanda allora davvero ... fa Where 1=1accadere cose brutte? E se sì, come posso dirlo?

Modifica minore: ho sempre anche "ipotizzato" che 1=1sarebbe stato ottimizzato o, nel peggiore dei casi, trascurabile. Non fa mai male mettere in discussione un mantra, come "Goto's are Evil" o "Premature Optimization ..." o altri fatti ipotizzati. Non ero sicuro che 1=1 ANDavrebbe influenzato realisticamente i piani di query o meno. Che dire delle sottoquery? Di CTE? Procedure?

Non sono uno da ottimizzare, a meno che non sia necessario ... ma se sto facendo qualcosa di veramente "cattivo", vorrei minimizzare gli effetti o cambiare dove applicabile.


2
No, non lo sarebbe. A parte alcuni microsecondi per l'ottimizzatore per rimuovere la condizione ridondante. Ti concentri meglio sul fatto che i tuoi letterali non siano ambigui.
ypercubeᵀᴹ

Come ha detto @ypercube, non fa differenza. Query Optimizer dovrebbe essere un pezzo di **** perché una cosa del genere faccia la differenza;)
Phil

4
Non credere a tutto ciò che leggi su reddit. Per favore.
Aaron Bertrand

1
@AaronBertrand Prendo tutto con un granello di sale, fino a quando non l'ho provato in prima persona. Prenderò ancora una domanda che sembra plausibile e vedrò se c'è della verità, specialmente quando influisce sul mio lavoro quotidiano.
WernerCD,

4
Ci sono granelli di sale, poi c'è il contenuto di sale di un intero oceano scaricato in cima all'edificio del tuo ufficio: P
Phil

Risposte:


13

Il server SQL parserL'ottimizzatore ha una funzione chiamata "Piegatura costante" che elimina le espressioni tautologiche dalla query.
Se guardi il piano di esecuzione, da nessuna parte nei predicati vedrai apparire quell'espressione. Ciò implica che la piegatura costante viene eseguita comunque in fase di compilazione per questo e altri motivi e non ha alcun effetto sulle prestazioni della query.

Per ulteriori informazioni, consultare la valutazione della piegatura e dell'espressione costanti durante la stima della cardinalità .


Probabilmente è stato compilato perché questo è un modello noto per concatenare i campi.
jcolebrand

No, viene compilato perché è tautologico. Funzionerebbe allo stesso modo con 2736 = 2736, che non è altrettanto normale di 1 = 1. Lo stesso vale per le contraddizioni. In tal caso la funzione si chiama "Rilevazione della contraddizione".
spaghettidba,

Quale parte del "modello noto" significa "deve essere 1 = 1"?
jcolebrand

9

L'aggiunta del predicato ridondante può fare la differenza in SQL Server.

Nei piani di esecuzione di seguito notare il @1nel primo piano contro il letterale 'foo'nel secondo piano.

inserisci qui la descrizione dell'immagine

Ciò indica che SQL Server ha considerato la prima query per una semplice parametrizzazione per promuovere il riutilizzo del piano di esecuzione, tuttavia il confronto tra due costanti impedisce che ciò accada nel secondo caso.

Un elenco di condizioni che impediscono la semplice parametrizzazione (precedentemente nota come auto-parametrizzazione) è disponibile nell'Appendice A del Plan Caching Microsoft Technical Papers:

la semplice parametrizzazione non è generalmente qualcosa su cui dovresti fare affidamento comunque. È molto meglio parametrizzare esplicitamente le tue query.


4

In qualsiasi RDBMS moderno (inclusi Oracle, Microsoft SQL Server e PostgreSQL - ne sono sicuro), ciò non avrà alcun effetto sulle prestazioni.

Come notato da qualcuno, ciò avrà effetto solo sulla fase di pianificazione delle query. Quindi la differenza sarà visibile solo quando si eseguono migliaia di iterazioni di una query semplicistica che non restituisce alcun dato, come questo:

SELECT 1 FROM empty_table; -- run this 10 000 times.

SELECT 1 FROM empty_table WHERE 1=1; -- run this 10 000 times and compare.

Per me, su PostgreSQL 9.0, questo è visibile con solo 10000 iterazioni:

filip@srv:~$ pgquerybench.pl -h /var/run/postgresql/ -q "select 1 from never where 1=1" -q "select 1 from never" -i 10000
Iterations: 10000
Query:   select 1 from never where 1=1
Total:   2.952 s
Average: 0.295 ms
Query:   select 1 from never
Total:   2.850 s
Average: 0.285 ms

0

Questo può essere un "problema" per Oracle quando si utilizza il parametro database cursore_sharing. Quando è impostato su "force", modificherà tutte le istruzioni SQL. Tutte le "costanti" nelle query saranno sostituite da variabili di bind (come 1 =>: SYS_0).

Questa opzione è stata introdotta per gestire alcuni sviluppatori pigri. D'altra parte può anche danneggiare altri sviluppatori pigri. Ma il rischio non è troppo elevato. Da 11g ha funzionalità di sbirciamento variabile vincolante.


Puoi chiarire cosa "A partire da 11g ha una funzione di sbirciamento variabile". si intende?
ypercubeᵀᴹ

@ypercube "Peeking di variabili bind" significa che l'ottimizzatore osserverà i valori effettivi delle variabili di bind e utilizzerà le statistiche dei dati per rivalutare ed eventualmente rigenerare il piano di esecuzione della query. Dubito che la sbirciatina avrà comunque alcun effetto sul costrutto di cui si sta discutendo, poiché non dipende dalle statistiche dei dati.
Mustaccio
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.