Usando GUIDs em chaves primárias/índices agrupados
-
16-09-2019 - |
Pergunta
Sou bastante versado no desempenho do servidor SQL, mas constantemente tenho que argumentar contra a ideia de que GUIDs devem ser usados como o tipo padrão para chaves primárias Clusterd.
Supondo que a tabela tenha uma quantidade bastante baixa de inserções por dia (5.000 +/- linhas/dia), que tipo de problemas de desempenho poderíamos encontrar?Como as divisões de páginas afetarão nosso desempenho de busca?Com que frequência devo reindexar (ou desfragmentar)?Como devo definir os fatores de preenchimento (100, 90, 80, ect)?
E se eu estivesse inserindo 1.000.000 de linhas por dia?
Peço desculpas antecipadamente por todas as perguntas, mas estou procurando algum backup por não usar GUIDs como padrão para PKs.No entanto, estou completamente aberto a mudar de ideia pelo conhecimento esmagador da base de usuários do StackOverflow.
Solução
Se você estiver fazendo qualquer tipo de volume, os GUIDs são extremamente ruins como um PK ruim, a menos que você use GUIDs sequenciais, pelas razões exatas que você descreve. A fragmentação da página é grave:
Average Average
Fragmentation Fragment Fragment Page Average
Type in Percent Count Size Count Space Used
id 4.35 7 16.43 115 99.89
newidguid 98.77 162 1 162 70.90
newsequentualid 4.35 7 16.43 115 99.89
E como esta comparação entre GUIDs e números inteiros mostra:
O Teste1 causou uma enorme quantidade de divisões de páginas e teve uma densidade de digitalização em torno de 12% quando executei um DBCC SHOWCONTIG após a conclusão das inserções.A tabela Test2 teve uma densidade de varredura em torno de 98%
Se o seu volume estiver muito baixo, entretanto, isso não importa muito.
Se você realmente precisa de um ID globalmente exclusivo, mas tem um volume alto (e não pode usar IDs sequenciais), basta colocar os GUIDs em uma coluna indexada.
Outras dicas
Desvantagens de usar GUID como chave primária:
- Nenhuma ordem significativa significa que a indexação não aumenta o desempenho como acontece com um número inteiro.
- Tamanho de um GUID 16 bytes, versus 2, 4 ou 8 bytes para um número inteiro.
- Muito difícil para os humanos lembrarem, então não serve como identificação de referência.
Vantagens:
- Permitir chaves primárias não adivinháveis que podem, portanto, ser menos perigosas quando exibidas em uma string de consulta de página da web ou no aplicativo.
- Útil em bancos de dados que não fornecem um incremento automático ou tipo de dados de identidade.
- Útil quando você precisa unir dados entre duas fontes de dados diferentes em plataformas ou ambientes.
Achei que a decisão de usar GUIDs era bem simples, mas talvez eu não tenha conhecimento de outros problemas.
Com um número tão baixo de inserções por dia, duvido que a divisão de páginas seja um fator significativo.A verdadeira questão é como 5.000 se compara à contagem de linhas existente, já que esta seria a principal informação necessária para decidir sobre um fator de preenchimento inicial apropriado para diferir divisões.
Dito isto, pessoalmente não sou um grande fã de GUIDs.Eu entendo que eles podem servir bem em alguns contextos, mas em muitos casos eles estão apenas “atrapalhando” [da eficiência, da facilidade de uso, de...]
Acho as seguintes perguntas úteis para decidir se o GUID deve ser usado ou não.
- O PK será compartilhado/publicado?(ou seja,será usado além de seu uso interno no SQL, os aplicativos precisarão dessas chaves de maneira um tanto persistente?Os usuários de alguma forma verão essas chaves?
- A PK poderia ser usada para ajudar a mesclar fontes de dados diferentes?
- A tabela tem um primário - possivelmente composto - feito de colunas nos dados?Qual é o tamanho desta possível chave
- Como as chaves primárias são classificadas?Se for composto, as primeiras colunas são seletivas?
Usar um guid (a menos que seja um GUID sequencial) como um índice clusterizado prejudicará o desempenho da inserção.Como o layout da tabela física está alinhado de acordo com o índice clusterizado, o uso de um guid que tenha uma ordem de sequenciamento aleatória causará séria fragmentação da tabela.Se você quiser usar um guid como um índice PK/Clustered, ele deve ser um guid sequencial usando a função newsequentialid() no sql server.Isto garantirá que os guias gerados sejam ordenados sequencialmente e evitará a fragmentação.