L'ordine delle colonne in un indice PK è importante?
Sì lo fa.
Per impostazione predefinita, il vincolo della chiave primaria viene applicato in SQL Server da un indice cluster univoco. L'indice cluster definisce l' ordine logico delle righe nella tabella. Potrebbero esserci un numero di pagine di indice extra aggiunte per rappresentare i livelli superiori dell'indice b-tree, ma il livello più basso (foglia) di un indice cluster è semplicemente l'ordine logico dei dati stessi.
Per essere chiari a questo proposito, le righe su una pagina non sono necessariamente archiviate fisicamente nell'ordine delle chiavi dell'indice cluster. C'è una struttura di indiretta separata all'interno della pagina che memorizza un puntatore a ogni riga. Questa struttura è ordinata in base alle chiavi di indice cluster. Inoltre, ogni pagina ha un puntatore alla pagina precedente e successiva allo stesso livello in ordine di chiave indice cluster.
Con una chiave primaria cluster di (RowNumber, DataDate)
, le righe vengono logicamente ordinate prima per RowNumber
e poi per DataDate
- quindi tutte le righe dove RowNumber = 1
sono raggruppate logicamente insieme, quindi le righe dove RowNumber = 2
e così via.
Quando si aggiungono nuovi dati (con RowNumbers
da 1 a n) le nuove righe appartengono logicamente alle pagine esistenti, quindi SQL Server probabilmente dovrà fare molto lavoro per dividere le pagine per fare spazio. Tutta questa attività genera molto lavoro extra (inclusa la registrazione delle modifiche) senza alcun guadagno.
Anche le pagine divise iniziano vuote per circa il 50%, quindi una divisione eccessiva può comportare una bassa densità di pagina (meno righe dell'ottimale per pagina). Questa brutta notizia non è solo per la lettura dal disco (densità inferiore = più pagine da leggere), ma anche le pagine a densità inferiore occupano più spazio in memoria quando vengono memorizzate nella cache.
La modifica dell'indice cluster in (DataDate, RowNumber
) significa che i nuovi dati (con, presumibilmente, più elevati di DataDates
quelli attualmente memorizzati) vengono aggiunti alla fine logica dell'indice cluster su nuove pagine. Ciò rimuoverà le spese generali non necessarie della divisione delle pagine e si tradurrà in tempi di caricamento più rapidi. Dati meno frammentati significano anche che l'attività read-ahead (lettura di pagine dal disco appena prima che siano necessarie per una query in corso) può essere più efficiente.
Se non altro, le query sono molto più probabile per cercare DataDate
di RowNumber
. Un indice cluster attivato (DataDate, RowNumber
) supporta l'indice cerca DataDate
(e quindi RowNumber
). La disposizione esistente supporta solo le ricerche su RowNumber
(e solo allora, forse, su DataDate
). Potresti riuscire a rilasciare l'indice non cluster esistente DataDate
una volta modificata la chiave primaria. L'indice cluster sarà più ampio dell'indice non cluster che sostituisce, quindi è necessario verificare per garantire che le prestazioni rimangano accettabili.
Quando si importano nuovi dati con bcp
, è possibile ottenere prestazioni più elevate se i dati all'interno del file di importazione vengono ordinati in base alle chiavi di indice cluster (idealmente (DataDate, RowNumber
)) e si specifica l' bcp
opzione:
-h "ORDER(DataDate,RowNumber), TABLOCK"
Per prestazioni ottimali di caricamento dei dati, è possibile provare a ottenere inserti con registrazione minima. Per ulteriori informazioni, vedere: