Sequenziale Guid e la frammentazione
-
27-09-2019 - |
Domanda
Sto cercando di capire come sequenziale esegue GUID meglio di un guid regolare.
E 'perché con guid regolare, l'indice di utilizzare l'ultimo byte del GUID per ordinare? Dal momento che è casuale causerà un sacco di frammentazione e della pagina divide dal momento che spesso spostare i dati ad un'altra pagina per inserire nuovi dati?
Sequenziale guid sine è sequenziale causerà molto meno divisioni di pagina e la frammentazione?
E 'la mia comprensione corretta?
Se qualcuno può far più luci su questo argomento, io molto apprezzato.
Grazie
EDIT:
Sequenziale guid = NEWSEQUENTIALID (),
regolare guid = NEWID ()
Soluzione
Hai praticamente detto tutto nella sua interrogazione.
Con un sequenziale GUID / chiave primaria nuove righe verranno aggiunti insieme alla fine del tavolo, che rende le cose belle un facile per il server SQL. In confronto un casuale mezzo di chiave primaria che i nuovi record potrebbero essere inseriti in qualsiasi parte del tavolo - la possibilità dell'ultima pagina per la tabella di essere nella cache è abbastanza probabile (se è lì che tutte le letture stanno andando), tuttavia la possibilità di una pagina a caso nel centro del tavolo essendo nella cache è abbastanza basso, il che significa ulteriore IO è necessaria.
In cima a quello, quando si inserisce righe nella centro del tavolo c'è la possibilità che non c'è abbastanza spazio per inserire la riga in più. Se questo è il caso, allora esigenze del server SQL per eseguire ulteriori costose operazioni di IO, al fine di creare spazio per la cronaca - l'unico modo per evitare questo è di avere lacune sparsi tra i dati per consentire per i record in più da inserire (conosciuto come un fattore di riempimento), che di per sé provoca problemi di prestazioni perché i dati si sviluppa su più pagine e quindi più IO è necessario per accedere l'intera tabella.
Altri suggerimenti
Mi rimetto alla saggezza di Kimberly L. Tripp su questo argomento:
Ma, un GUID che non è sequenziale - come uno che ce l'ha di valori generato nel client (utilizzando .NET) O generate dal newid funzione () (In SQL Server) può essere una cattiva orribilmente scelta - soprattutto a causa del frammentazione che si crea nel tabella di base ma anche per la sua dimensione. E 'inutilmente ampia (è 4 volte più larga un'identità int-based - che può dare 2 miliardi (in realtà, 4 miliardi) righe univoche). E, se avete bisogno di più di 2 miliardi di te può sempre andare con un bigint (8 byte int) e ottenere 263-1 righe.
Per saperne di più: http://www.sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx#ixzz0wDK6cece
Per visualizzare l'immagine intera util denominato OSTRESS potrebbe essere utilizzato. Per esempio. è possibile creare due tabelle: una con normale GUID come PK, un altro con GUID sequenziale:
-- normal one
CREATE TABLE dbo.YourTable(
[id] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_YourTable] PRIMARY KEY NONCLUSTERED (id)
);
-- sequential one
CREATE TABLE dbo.YourTableSeq(
[id] [uniqueidentifier] NOT NULL CONSTRAINT [df_yourtable_id] DEFAULT (newsequentialid()),
CONSTRAINT [PK_YourTableSeq] PRIMARY KEY NONCLUSTERED (id)
);
Poi, con un dato util si esegue un numbero di inserti con la selezione di statistiche su indice di frammentazione:
ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTable VALUES (NEWID()); SELECT count(*) AS Cnt FROM dbo.YourTable; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTable';" -oE:\incoming\TMP\ -n1 -r10000
ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTableSeq DEFAULT VALUES; SELECT count(*) AS Cnt FROM dbo.YourTableSeq; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTableSeq';" -oE:\incoming\TMP\ -n1 -r10000
Poi, nel file E: \ incoming \ TMP \ query.out troverete le statistiche. I miei risultati sono i seguenti:
"Normal" GUID:
Records AvgPageFragmentation PageCounts
----------------------------------------------
1000 87.5 8
2000 93.75 16
3000 96.15384615384616 26
4000 96.875 32
5000 96.969696969696969 33
10000 98.571428571428584 70
Sequential GUID:
Records AvgPageFragmentation PageCounts
----------------------------------------------
1000 83.333333333333343 6
2000 63.636363636363633 11
3000 41.17647058823529 17
4000 31.818181818181817 22
5000 25.0 28
10000 12.727272727272727 55
Come si può vedere con GUID sequenziale generato essendo inserito, indice è molto meno frammentata i conduttori operazione di inserimento a nuova rari allocazione di pagina.