Guia sequencial e fragmentação
-
27-09-2019 - |
Pergunta
Estou tentando entender como o guid sequencial tem melhor desempenho do que um guid normal.
É porque com o guid regular, o índice usa o último byte do guid para classificar?Por ser aleatório, causará muita fragmentação e divisões de páginas, pois muitas vezes moverá dados para outra página para inserir novos dados?
Guia senoidal sequencial é sequencial e causará muito menos divisões e fragmentação de páginas?
Meu entendimento está correto?
Se alguém puder esclarecer mais sobre o assunto, agradecerei muito.
Obrigado
EDITAR:
Guid sequencial = NEWSEQUENTIALID(),
Guia normal = NEWID()
Solução
Você praticamente disse tudo em sua pergunta.
Com um GUID/chave primária sequencial, novas linhas serão adicionadas no final da tabela, o que torna as coisas fáceis para o SQL Server.Em comparação, uma chave primária aleatória significa que novos registros podem ser inseridos em qualquer lugar da tabela - a chance da última página da tabela estar no cache é bastante provável (se é para lá que todas as leituras estão indo), no entanto, a chance de uma página aleatória no meio da tabela no cache é bastante baixa, o que significa que é necessária E/S adicional.
Além disso, ao inserir linhas no meio da tabela existe a possibilidade de não haver espaço suficiente para inserir a linha extra.Se for esse o caso, o SQL Server precisará executar operações IO adicionais e caras para criar espaço para o registro - a única maneira de evitar isso é ter lacunas espalhadas entre os dados para permitir a inserção de registros extras (conhecido como um Fator de preenchimento), o que por si só causa problemas de desempenho porque os dados estão espalhados por mais páginas e, portanto, é necessário mais IO para acessar a tabela inteira.
Outras dicas
Defer à sabedoria de Kimberly L. Tripp sobre este tópico:
Mas, um guia que não é seqüencial - como um que possui seus valores gerados no cliente (usando .NET) ou gerado pela função newid () (no servidor SQL) pode ser uma escolha terrivelmente ruim - principalmente por causa da fragmentação que Ele cria na tabela base, mas também por causa de seu tamanho. É desnecessariamente largo (é 4 vezes mais largo que uma identidade baseada em INT - que pode oferecer 2 bilhões de linhas únicas (realmente, 4 bilhões)). E, se você precisar de mais de 2 bilhões, sempre poderá usar um Bigint (8 bytes Int) e obter 263-1 linhas.
Consulte Mais informação: http://www.sqlskills.com/blogs/kimberly/post/guids-as-primary-keys-andor-the-cluering-key.aspx#ixzz0wdk6cece
Para visualizar a imagem inteira Util nomeado Ostress pode ser usado. Por exemplo, você pode criar duas tabelas: uma com normal Guid como PK, outro com Guid sequencial:
-- 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)
);
Então, com um determinado Util, você executa várias inserções com a seleção de estatísticas sobre a fragmentação do índice:
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
Então, no arquivo e: recebendo tmp query.out, você encontrará suas estatísticas. Meus resultados são:
"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
Como você pode ver com o GUID gerado sequencialmente sendo inserido, o índice é muito menos fragmentado à medida que a operação de inserção leva à nova alocação de página mais rara.