Pergunta

Tenho várias tabelas cujos únicos dados exclusivos são uma coluna uniqueidentifier (um Guid).Como os guids não são sequenciais (e são gerados pelo lado do cliente, portanto não posso usar newsequentialid()), criei um índice não primário e não agrupado neste campo de ID, em vez de fornecer às tabelas um índice primário agrupado chave.

Estou me perguntando quais são as implicações de desempenho para essa abordagem.Já vi algumas pessoas sugerirem que as tabelas deveriam ter um int de incremento automático ("identidade") como uma chave primária agrupada, mesmo que não tenha nenhum significado, pois significa que o próprio mecanismo de banco de dados pode usar esse valor para rapidamente procure uma linha em vez de usar um marcador.

Meu banco de dados é replicado por mesclagem em vários servidores, por isso evitei colunas de identidade int, pois elas são um pouco complicadas para acertar na replicação.

Quais são seus pensamentos?As tabelas devem ter chaves primárias?Ou não há problema em não ter índices clusterizados se não houver colunas sensíveis para indexar dessa forma?

Foi útil?

Solução

Ao lidar com índices, você deve determinar para que sua tabela será usada.Se você estiver inserindo principalmente 1.000 linhas por segundo e não fazendo nenhuma consulta, um índice clusterizado afetará o desempenho.Se você estiver fazendo 1.000 consultas por segundo, não ter um índice resultará em um desempenho muito ruim.A melhor coisa a fazer ao tentar ajustar consultas/índices é usar o Query Plan Analyzer e o SQL Profiler no SQL Server.Isso mostrará onde você está enfrentando varreduras de tabela dispendiosas ou outros bloqueadores de desempenho.

Quanto ao argumento GUID vs ID, você pode encontrar pessoas online que confiam em ambos.Sempre fui ensinado a usar GUIDs, a menos que tenha um bom motivo para não fazê-lo.Jeff tem um bom post que fala sobre os motivos para usar GUIDs: https://blog.codinghorror.com/primary-keys-ids-versus-guids/.

Como acontece com quase tudo relacionado ao desenvolvimento, se você deseja melhorar o desempenho, não existe uma única resposta certa.Realmente depende do que você está tentando realizar e de como está implementando a solução.A única resposta verdadeira é testar, testar e testar novamente em relação às métricas de desempenho para garantir que você está atingindo seus objetivos.

Editar] @Matt, depois de fazer mais algumas pesquisas sobre o debate do GUID/ID, deparei -me com este post.Como mencionei antes, não existe uma resposta certa ou errada.Depende de suas necessidades específicas de implementação.Mas estes são alguns motivos bastante válidos para usar GUIDs como chave primária:

Por exemplo, existe um problema conhecido como “hotspot”, onde certas páginas de dados de uma tabela estão sob uma contenção monetária relativamente alta.Basicamente, o que acontece é que a maior parte do tráfego em uma tabela (e, portanto, dos bloqueios no nível da página) ocorre em uma pequena área da tabela, no final.Novos registros sempre irão para este hotspot, pois IDENTITY é um gerador de números sequenciais.Essas inserções são problemáticas porque exigem bloqueio de página exclusivo na página à qual são adicionadas (o ponto de acesso).Isso serializa efetivamente todas as inserções em uma tabela graças ao mecanismo de bloqueio de página.NewID(), por outro lado, não sofre de pontos de acesso.Os valores gerados usando a função NewID() são sequenciais apenas para pequenas sequências de inserções (onde a função está sendo chamada muito rapidamente, como durante uma inserção de várias linhas), o que faz com que as linhas inseridas se espalhem aleatoriamente pelas páginas de dados da tabela. de tudo no final - eliminando assim um ponto de acesso das inserções.

Além disso, como as inserções são distribuídas aleatoriamente, a chance de divisões de página é bastante reduzida.Embora uma página dividida aqui e ali não seja tão ruim, os efeitos aumentam rapidamente.Com IDENTITY, o fator de preenchimento da página é bastante inútil como mecanismo de ajuste e pode muito bem ser definido como 100% - as linhas nunca serão inseridas em nenhuma página, exceto na última.Com NewID(), você pode realmente usar o Fill Factor como uma ferramenta de melhoria de desempenho.Você pode definir o fator de preenchimento para um nível que se aproxime do crescimento estimado do volume entre recriações de índice e, em seguida, programar as recriações fora dos horários de pico usando a reindexação dbcc.Isso atrasa efetivamente os impactos de desempenho das divisões de página até horários fora de pico.

Se você mesmo pensar talvez seja necessário ativar a replicação para a tabela em questão - então você também pode tornar o PK um identificador exclusivo e sinalizar o campo guid como ROWGUIDCOL.A replicação exigirá um campo guid de valor exclusivo com este atributo e adicionará um se não existir nenhum.Se existir um campo adequado, ele usará apenas aquele que estiver lá.

Outro grande benefício do uso de GUIDs para PKs é o fato de que o valor é realmente garantido como único - não apenas entre todos os valores gerados por esse servidor, mas todos os valores gerados por todos computadores - seja seu servidor db, servidor web, servidor de aplicativo ou máquina cliente.Praticamente todas as linguagens modernas têm a capacidade de gerar um guia válido agora - no .NET você pode usar System.Guid.NewGuid.Isso é MUITO útil ao lidar com conjuntos de dados de detalhes mestres armazenados em cache, em particular.Você não precisa empregar esquemas malucos de codificação temporária apenas para relacionar seus registros antes de serem confirmados.Você acabou de buscar um novo Guid perfeitamente válido do sistema operacional para o valor da chave permanente de cada novo registro no momento em que o registro é criado.

http://forums.asp.net/t/264350.aspx

Outras dicas

A chave primária serve a três propósitos:

  • indica que as colunas devem ser exclusivas
  • indica que a(s) coluna(s) não deve(m) ser nulas
  • documentar a intenção de que este é o identificador exclusivo da linha

Os dois primeiros podem ser especificados de diversas maneiras, como você já fez.

A terceira razão é boa:

  • para humanos, para que eles possam ver facilmente sua intenção
  • para o computador, portanto, um programa que possa comparar ou processar sua tabela poderá consultar o banco de dados em busca da chave primária da tabela.

Uma chave primária não precisa ser um campo numérico de incremento automático, então eu diria que é uma boa ideia especificar sua coluna guid como a chave primária.

Estou apenas começando, porque Matt me incitou um pouco.

Você precisa entender que, embora um índice clusterizado seja colocado na chave primária de uma tabela por padrão, os dois conceitos são separados e devem ser considerados separadamente.Um CIX indica a forma como os dados são armazenados e referidos pelos NCIXs, enquanto o PK fornece uma exclusividade para cada linha para satisfazer os requisitos LÓGICOS de uma tabela.

Uma tabela sem CIX é apenas um Heap.Uma mesa sem PK é frequentemente considerada "não uma mesa".É melhor compreender os conceitos PK e CIX separadamente para que você possa tomar decisões sensatas no design do banco de dados.

Roubar

Ninguém respondeu à pergunta real:quais são os prós e contras de uma tabela SEM PK NEM um índice CLUSTERED.Na minha opinião, se você otimizar para inserções mais rápidas (especialmente inserção em massa incremental, por exemploquando você carrega dados em massa em uma tabela não vazia), tal tabela:sem índice clusterizado, SEM restrições, SEM chaves estrangeiras, SEM padrões e SEM chave primária, em um banco de dados com modelo de recuperação simples, é o melhor.Agora, se você quiser consultar esta tabela (em vez de verificá-la por completo), você pode querer adicionar índices não exclusivos não agrupados conforme necessário, mas mantê-los no mínimo.

Eu também sempre ouvi dizer que ter um int de incremento automático é bom para o desempenho, mesmo que você não o use.

Uma chave primária não precisa ser um campo de incremento automático; em muitos casos, isso significa apenas que você está complicando a estrutura da sua tabela.

Em vez disso, uma chave primária deve ser a coleção mínima de atributos (observe que a maioria dos SGBDs permitirá uma chave primária composta) que identifica exclusivamente uma tupla.

Em termos técnicos, deve ser o campo do qual todos os outros campos da tupla dependem totalmente funcionalmente.(Se não for, talvez seja necessário normalizar).

Na prática, problemas de desempenho podem significar que você mescla tabelas e usa um campo de incremento, mas parece que me lembro de algo sobre a otimização prematura ser má...

Como você está fazendo a replicação, suas identidades corretas são algo a ser evitado.Eu faria do seu GUID uma chave primária, mas não agrupada, pois você não pode usar o newsequentialid.Isso me parece o seu melhor caminho.Se você não fizer dele um PK, mas colocar um índice exclusivo nele, mais cedo ou mais tarde isso poderá fazer com que as pessoas que mantêm o sistema não entendam os relacionamentos FK introduzindo bugs adequadamente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top