Ho una tabella itemValue pieno di dati su un server SQL 2005 in esecuzione in modalità di compatibilità 2000 sembra qualcosa di simile (si tratta di una tabella di valori definiti dall'utente):Ottimizzazione SQL - il piano di esecuzione cambia in base al valore del vincolo - Perché?
ID ItemCode FieldID Value
-- ---------- ------- ------
1 abc123 1 D
2 abc123 2 287.23
4 xyz789 1 A
5 xyz789 2 3782.23
6 xyz789 3 23
7 mno456 1 W
9 mno456 3 45
... and so on.
fieldid viene da il ItemField tavolo:
ID FieldNumber DataFormatID Description ...
-- ----------- ------------ -----------
1 1 1 Weight class
2 2 4 Cost
3 3 3 Another made up description
. . x xxx
. . x xxx
. . x xxx
x 91 (we have 91 user-defined fields)
Perché non posso PIVOT in modalità 2000, siamo bloccati costruire una query di brutto utilizzando casi e GROUP BY per ottenere i dati di guardare come dovrebbe per s ome applicazioni legacy, che è:
ItemNumber Field1 Field2 Field3 .... Field51
---------- ------ ------- ------
abc123 D 287.23 NULL
xyz789 A 3782.23 23
mno456 W NULL 45
potete vedere abbiamo solo bisogno di questa tabella per mostrare valori fino a 51 ° UDF. Ecco la domanda:
SELECT
iv.ItemNumber,
,MAX(CASE WHEN f.FieldNumber = 1 THEN iv.[Value] ELSE NULL END) [Field1]
,MAX(CASE WHEN f.FieldNumber = 2 THEN iv.[Value] ELSE NULL END) [Field2]
,MAX(CASE WHEN f.FieldNumber = 3 THEN iv.[Value] ELSE NULL END) [Field3]
...
,MAX(CASE WHEN f.FieldNumber = 51 THEN iv.[Value] ELSE NULL END) [Field51]
FROM ItemField f
LEFT JOIN ItemValue iv ON f.ID = iv.FieldID
WHERE f.FieldNumber <= 51
GROUP BY iv.ItemNumber
Quando il vincolo FieldNumber è < = 51, l'esecuzione piano va qualcosa come:
SELECT <== Computer Scalar <== Stream Aggregate <== Sort (Cost: 70%) <== Hash Match <== (Clustered Index Seek && Table Scan)
ed è veloce! Posso ritirare oltre 100.000 dischi in circa un secondo, che si adatta alle nostre esigenze.
Tuttavia, se avessimo più UDF e modificare il vincolo a qualsiasi cosa sopra (sì, ho provato uno per uno) o se rimuovere completamente, perdo il Sort nel piano di esecuzione, ed è viene sostituito con un intero gruppo di blocchi di parallelismo che raccolgono, ripartizionano e distribuiscono flussi, e l'intera cosa è lenta (30 secondi anche per solo 1 record).
FieldNumber ha un cluster, indice univoco, ed è parte della chiave primaria composta con la ID colonna (indice non cluster) nella tavolo ItemField. Il itemValue della tabella ID e ItemNumber colonne fanno una PK, e v'è un ulteriore indice non cluster sulla colonna diItemNumber.
Qual è il ragionamento alla base di questo? Perché la modifica del mio semplice vincolo di intero modifica l'intero piano di esecuzione?
E se sei all'altezza ... cosa faresti diversamente? C'è un aggiornamento SQL pianificato per un paio di mesi, ma ho bisogno di risolvere questo problema prima.
Quello che farei diversamente non è usare quella struttura di tabella. È molto meglio utilizzare una struttura con campi definiti per il 99% delle esigenze di dati che possono essere individuate in anticipo rispetto all'utilizzo di una tabella EAV. Per inciso, la modalità compatilbity non ti impedisce di utilizzare nuove funzionalità, è di consentire l'utilizzo di funzionalità che non sono più consentite. Tuttavia, se si sta sviluppando su un database 2005 con un database di produzione 2000, è meglio evitare le nuove funzionalità. – HLGEM