Последовательный GUID и фрагментация
-
27-09-2019 - |
Вопрос
Я пытаюсь понять, как последовательный GUID выполняет лучше, чем регулярный GUID.
Это связано с помощью регулярного GUID, индекс использует последний байт GUID для сортировки? Поскольку это случайно, это приведет к тому, что много фрагментации и расщепления страниц, поскольку он часто будет перемещать данные на другую страницу, чтобы вставить новые данные?
Последовательный GUID SINE SINE SEQUINT, он приведет к тому, что намного меньше расщепляется и фрагментация страниц?
Является ли мое понимание правильно?
Если кто-то может пролить больше огней на эту тему, я очень оценил очень.
Спасибо
РЕДАКТИРОВАТЬ:
Последовательный GUID = NewsexentialID (),
Регулярный GUID = NewID ()
Решение
Вы в значительной степени сказали все это в вашем вопросе.
С помощью последовательного GUID / первичного ключа новые строки будут добавлены вместе в конце таблицы, что делает вещи приятными для SQL Server. По сравнению со случайным первичным ключом означает, что новые записи могут быть вставлены в любой точке таблицы - шанс последней страницы для таблицы, находящейся в кэше, довольно вероятно (если это где все чтения идут), однако шанс Случайная страница в середине таблицы, находящаяся в кеше, довольно низкая, что означает, что требуется дополнительный IO.
Кроме того, при вставке рядов в середину таблицы имеется вероятность того, что не хватает места для вставки дополнительной строки. Если это так, то SQL Server должен выполнить дополнительные дорогие операции IO, чтобы создать место для записи - единственным способом, которым можно избежать этого, - это разброс, разбросанные среди данных, чтобы обеспечить вставленные дополнительные записи (известные как Фактор заполнения), который сам по себе вызывает проблемы с производительностью, потому что данные распространяются по большему количеству страниц, и поэтому больше IO требуется для доступа к всей таблице.
Другие советы
Я отложил мудрость Кимберли Л. Трипп на эту тему:
Но GUID, который не является последовательным - подобным таким, таким образом, имеющим его значения, сгенерированные в клиенте (используя .NET) или сгенерированные функцией NewID () (на SQL Server) могут быть ужасно плохой выбор - в первую очередь из-за фрагментации, который Это создает в базовом столе, но и из-за его размера. Это излишне широко (в 4 раза больше, чем интенсивная идентичность, которая может дать вам 2 миллиарда (действительно, 4 миллиарда) уникальных строк). И, если вам нужно более 2 миллиардов, вы всегда можете пойти с Bigint (8-байт INT) и получите 263-1 строк.
Визуализировать всю картину Умитана названа остерс может быть использован. Например, вы можете создать две таблицы: один с обычный GUID как PK, другой с последовательным 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)
);
Затем с данным Util вы запускаете Nall of Instrics с выбором статистики о фрагментации индекса:
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
Затем в файле E: Incoming TMP Query.out Вы найдете свою статистику. Мои результаты:
"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
Как вы можете видеть с помощью последовательно сгенерированного руководства, индекс намного менее фрагментирован, поскольку операция вставки приводит к распределению новой страницы Rarer.