Sequenzielle Guid und Fragmentierung
-
27-09-2019 - |
Frage
Ich versuche, wie sequentielle guid besser abschneidet als ein normales guid zu verstehen.
Ist es, weil mit regelmäßigen guid, der Index das letzte Byte der GUID zu sortieren verwenden? Da es zufällig ist wird es eine Menge von Fragmentierung und Seitenteilungen verursachen, da es oft Daten auf eine andere Seite verschieben werden neue Daten einfügen?
Sequential guid Sinus ist es sequenzielle es wird dazu führen, viel weniger Seitenteilungen und Fragmentierung?
Ist mein Verständnis richtig?
Wenn jemand mehr Licht auf das Thema werfen kann, werde ich sehr geschätzt.
Danke
EDIT:
Sequential guid = NEWSEQUENTIALID ()
Regular guid = NEWID ()
Lösung
Sie haben gesagt, so ziemlich alles in Frage.
Mit einem sequenziellen GUID / Primärschlüssel neue Zeilen am Ende der Tabelle addiert werden, die Dinge schön ein einfach für SQL Server macht. Im Vergleich ein Zufallsprimärschlüssel bedeutet, dass neue Datensätze überall in der Tabelle eingefügt werden könnten - die Chance auf der letzten Seite der Tabelle im Cache zu sein, ist ziemlich wahrscheinlich (wenn das, wo alle die gehen lesen), aber die Chance, eine zufällige Seite in der Mitte der Tabelle im Cache ist ziemlich niedrig ist, zusätzliche IO Bedeutung erforderlich ist.
Hinzu kommt, dass, wenn Zeilen in die Mitte des Tisches Einsetzen gibt es die Chance, dass es nicht genug Platz ist, um die zusätzliche Zeile einzufügen. Wenn dies der Fall ist, dann SQL Server braucht, ist zusätzliche teure IO-Operationen durchzuführen, um Platz für den Datensatz zu erstellen - den einzigen Weg, dies zu vermeiden ist es, Lücken zwischen den Daten verstreut zu haben, um zusätzliche Datensätze zu ermöglichen (auch bekannt als ein eingefügt werden Füllfaktor), die an sich verursacht Leistungsprobleme, weil die Daten verteilt über mehrere Seiten ist und so mehr IO erforderlich, um die gesamte Tabelle zugreifen zu können.
Andere Tipps
ich aufschieben zu diesem Thema Kimberly L. Tripp Weisheit:
Aber eine GUID, die nicht sequentiell ist - wie einer, der es Werte hat erzeugt in dem Client (unter Verwendung von .NET) Oder durch die newid erzeugt () -Funktion (In SQL Server) kann ein schrecklich schlecht sein Wahl - vor allem wegen der Fragmentierung, die es in der schafft Basistabelle, sondern auch wegen seines Größe. Es ist unnötig breit (es ist 4 mal breiter als eine int-basierte Identität - das können Sie 2 Milliarden (wirklich, 4 Milliarden) eindeutige Zeilen). Und, wenn Sie brauchen mehr als 2 Milliarden Sie kann immer mit einem Bigint (8-Byte gehen int) und 263-1 Reihen erhalten.
Lesen Sie mehr über: http://www.sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx#ixzz0wDK6cece
Um das ganze Bild visualisieren util Namen OSTRESS verwendet werden könnten. Z.B. Sie können zwei Tabellen erstellen: eine mit normalen GUID als PK, eine andere mit sequentieller GUID:
-- 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)
);
Dann mit einem gegebenen util Sie eine numbero von Einsätzen mit einer Auswahl an Statistiken über Index-Fragmentierung ausführen:
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
Dann in der Datei E: \ incoming \ TMP \ query.out werden Sie Ihre Statistiken finden. Meine Ergebnisse sind:
"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
Wie Sie mit sequentiell erzeugt GUID wird eingefügt sehen können, wird der Index sehr viel weniger fragmentiert wie die Einfügeoperation führt zu neuen Seitenzuordnungs- seltener.