Cosa succede durante gli inserimenti "grandi" su una tabella con una chiave composita in cluster?


8

La mia conoscenza di SQL è limitata, quindi i termini che userò probabilmente non sono quelli giusti.

Ho una tabella che memorizzerà i risultati dei test, per più posizioni.

I test verranno registrati in database diversi in posizioni diverse (nessuna connessione di rete) e la posizione "master" "importerà" regolarmente i risultati del test dalle altre posizioni.

Ho in programma di avere una chiave primaria composita in cluster nelle colonne LocationId (int) e Date (datetime), in questo ordine. Il ragionamento è che dovrebbe mantenere tutti i risultati per una posizione insieme e non farò quasi mai una query per intervallo di date, ma piuttosto per intervallo di date e posizione.

La dimensione della riga sarà compresa tra 80 e 100 byte e il numero di risultati del test non dovrebbe superare alcuni milioni. Una "importazione" tipica inserirà da 50 a 100 mila risultati da un'altra posizione.

Cosa succederà durante le importazioni? SQL "sposta" le righe esistenti per mantenere il clustering o consente alla tabella di diventare "frammentata"? Ciò potrebbe causare un notevole calo delle prestazioni se l'importazione viene eseguita una riga alla volta? Dovrei piuttosto non preoccuparmi dell'ordinamento delle righe e aggiungere semplicemente una colonna di identità come chiave primaria e un indice nella colonna Data per aiutarmi con le mie query?

Risposte:


19

Vacca santa, hai molte domande qui. Analizziamo questo.

D: SQL "sposta" le righe esistenti per mantenere il clustering o consente alla tabella di diventare "frammentata"?

Pensa a un database come a una raccolta di pagine: letterali pezzi di carta disposti sulla tua scrivania. Pensa al dizionario per ora. Se si desidera aggiungere più parole al dizionario, è possibile aggiungerle se le pagine hanno spazio vuoto.

Quando inizi con un dizionario vuoto, questo è relativamente semplice. Ma pensa a un dizionario maturo con migliaia di pagine di carta, tutte piene.

Quando vuoi aggiungere più parole a quel dizionario maturo, è probabile che non ci sarà più spazio sulla pagina. SQL Server "strapperà" una pagina: ci vorrà una pagina nuova di zecca altrove e sposta alcune delle parole su quella nuova pagina. La nuova pagina sarebbe alla fine del dizionario. La buona notizia è che subito dopo quell'azione, ora c'è una pagina semivuota alla fine del dizionario e anche al centro, entrambe con spazio per aggiungere parole.

Se ti capita di aggiungerli in quell'ordine, cioè. (Ecco perché il modo in cui carichi i dati diventa sempre più importante.)

Ciò potrebbe causare un notevole calo delle prestazioni se l'importazione viene eseguita una riga alla volta?

Dimentica l'indice per un secondo - l'aggiunta di dati una riga alla volta è semplicemente inefficiente indipendentemente dalla struttura dell'indicizzazione. SQL Server è un sistema basato su set: ogni volta che puoi lavorare in set, probabilmente dovresti.

Cosa succede quando eseguo una query sui dati?

Non me l'hai chiesto, ma te lo sto chiedendo, hahaha.

Ripensa alle conseguenze dei nostri inserti. Ora abbiamo un dizionario che è per lo più ordinato, ma quando arrivi ad alcuni punti del dizionario, dovrai saltare sul retro per leggere da poche altre pagine. Se queste pagine sono tutte memorizzate nella cache (RAM, pool di buffer, ecc.), L'overhead non sarà così grande. La maggior parte dell'accesso alla memoria è casuale, non è come se SQL Server memorizzasse il dizionario in ordine.

D'altra parte, se è necessario recuperare i dati dai dischi rigidi magnetici convenzionali (ruggine che gira), è possibile ottenere un vantaggio in termini di prestazioni se i dati vengono archiviati in ordine. Il vero obiettivo di progettazione qui, tuttavia, è quello di ottenere i dati dalla RAM invece di ottenerli dalle unità. La differenza tra i dati deframmentati su disco rispetto ai dati frammentati su disco non è affatto significativa quanto la differenza tra ottenerli dal disco e ottenerli dalla RAM .

Dovrei piuttosto non preoccuparmi dell'ordinamento delle righe e aggiungere semplicemente una colonna di identità come chiave primaria e un indice nella colonna Data per aiutarmi con le mie query?

Bingo: questa è la differenza tra la progettazione fisica del database e la progettazione logica del database. I programmatori devono preoccuparsi molto della progettazione fisica del database inizialmente, ma finché il database è sotto, diciamo, con dimensioni di 100 GB, è possibile correggere la progettazione logica in post, per così dire. Metti un campo identità lì per cominciare, raggruppalo su di esso e poi, dopo essere stato attivo per alcuni mesi, rivisita il design dell'indice per massimizzare le prestazioni.

Ora, detto questo, una volta che hai sperimentato questo tipo di processo decisionale, allora sarai meglio attrezzato per indovinare gli indici fin dall'inizio. Anche così, di solito non ho nemmeno pensato molto alla progettazione dell'indice inizialmente. Gli utenti non sembrano mai interrogare i dati come mi sarei aspettato.


1
L'inserto uno per uno era una domanda teorica. Mi è sembrato dubbio, dal punto di vista delle prestazioni, che "le righe sono archiviate fisicamente sul disco nello stesso ordine dell'indice cluster" che hai letto nella maggior parte dei casi.
Sacha K,

Vado per una colonna di identità. I dati verranno aggiunti "alla fine" e naturalmente ordinati per data. Le stesse date per località diverse non saranno "vicine tra loro", ma per me non importa affatto.
Sacha K,
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.