Pergunta

Até agora eu estive usando o C # "Guid = Guid.NewGuid ();" método para gerar uma identificação única que pode ser armazenado como o campo ID em algumas das minhas tabelas de banco de dados SQL Server usando o LINQ to SQL. Fui informado que, por razões de indexação, usando um GUID é uma má idéia e que eu deveria usar um auto-incremento longo vez. Irá usar um longo acelerar o meu transações de banco de dados? Se sim, como faço para ir sobre a geração de ID únicos que são do tipo Long?

Saudações,

Foi útil?

Solução

Ambos têm prós e contras, isso depende inteiramente de como você usá-los o que importa.

Logo de cara, se você precisar de identificadores que podem trabalhar em vários bancos de dados, você precisa de GUIDs. Existem alguns truques com Long (atribuir manualmente cada banco de dados a diferentes semente / incremento), mas estes não escala bem.

Quanto indexação vai, Long dará muito melhor inserção desempenho se o índice está em cluster (por padrão chaves primárias estão agrupados, mas isso pode ser modificado para sua mesa), uma vez que a tabela não precisa ser reorganizado após cada inserção.

Quanto inserções concorrentes estão em causa no entanto, longas (identidade) colunas será mais lento, em seguida, GUID - geração coluna de identidade requer uma série de bloqueios exclusivos para garantir que apenas uma linha recebe o próximo número seqüencial. Em um ambiente com muitos usuários inserir muitas linhas o tempo todo, isso pode ser um acerto de desempenho. geração GUID nesta situação é mais rápido.

Armazenamento sábio, um GUID ocupa duas vezes o espaço de um Long (8 bytes vs 16). No entanto, depende do tamanho global da sua linha se 8 bytes vai fazer uma diferença notável em quantos registros caber em uma folha, e, portanto, o número de folhas puxados a partir do disco durante uma solicitação média.

Outras dicas

Um longo (grande int no sql server) é de 8 bytes e um Guid é de 16 bytes, para que sejam reduzir para metade o número de servidor os bytes SQL tem de comparar ao fazer um olhar para cima.

Para gerar um longo, IDENTIDADE uso (1,1) quando você cria o campo no banco de dados.

por isso ou usando CREATE TABLE ou ALTER TABLE:

Field_NAME BIGINT NOT NULL PRIMARY KEY IDENTITY(1,1)

Ver comentários postagem LINQ to SQL

A "Rainha do indexação" - Kim Tripp - basicamente diz tudo em seu indexando posts:

Basicamente, sua melhores práticas são: uma chave de cluster ideal deve ser:

  • única
  • pequena
  • estável (nunca mudando)
  • crescente

O GUID violar a "pequena" e "crescente" e, portanto, não são ideais.

PLUS: todas as suas chaves de cluster será adicionado a cada entrada única em cada um e cada índice não agrupado (como a pesquisa para realmente encontrar o registro no banco de dados), assim que você quer para torná-los tão pequenos quanto possível (INT = 4 bytes vs GUID = 16 bytes). Se você tem centenas de milhões de linhas e vários índices não agrupados, a escolha de um INT ou BIGINT mais de um GUID pode fazer uma grande diferença -. Mesmo apenas espaço-wise

Marc

Use guids quando você precisa considerar importação / exportação para vários bancos de dados. Guids são muitas vezes mais fácil de usar do que colunas especificando o atributo IDENTITY quando se trabalha com um conjunto de dados de múltiplas relações criança. isso é porque você pode gerar aleatoriamente guids no código em um estado desconectado do banco de dados, e em seguida, enviar todas as alterações de uma só vez. Quando guids são gerados corretamente, eles são insainely difícil de duplicar por acaso. Com colunas de identidade, muitas vezes você tem que fazer uma inserção inicial de uma linha pai e consulta para a sua nova identidade antes de adicionar dados criança. Você então tem que atualizar todos os registros filho com a nova identidade dos pais antes de cometer-los para o banco de dados. O mesmo vale para os netos e assim por diante para baixo da hierarquia. Acumula-se a um monte de trabalho que parece desnecessário e mundano. Você pode fazer algo semelhante ao Guids por comming com inteiros aleatórios sem a especificação de identidade, mas a chance de colisão é muito maior que você inserir mais registros ao longo do tempo. (Guid.NewGuid () é semelhante a um Int128 aleatória - que ainda não existe).

Eu uso Byte (TinyInt), Int16 (smallint), Int32 / UInt16 (Int), Int64 / UInt32 (BigInt) para listas de pesquisa pequenos que não mudam ou dados que não replicar entre vários bancos de dados. (As permissões, configuração de aplicativos, nomes de cores, etc.)

Eu imagino que a indexação leva o mesmo tempo para consulta contra independentemente se você estiver usando um guid ou uma longa. Normalmente existem outros campos em tabelas que são indexados que são maiores do que 128 bits de qualquer maneira (nomes de usuário em uma tabela de usuário, por exemplo). A diferença entre Guids e Inteiros é o tamanho do índice na memória, bem como povoamento tempo e índices de reconstrução. A maioria das operações de banco de dados é muitas vezes a leitura. Escrever é mínima. Concentrado em otimizar a leitura do banco de dados em primeiro lugar, como eles são normalmente feitas de tabelas associadas que não foram otimizados corretamente, paginação imprópria, ou índices ausentes.

Como com qualquer coisa, a melhor coisa a fazer é para provar seu ponto. criar um banco de dados de teste com duas tabelas. Um com uma chave primária de inteiros / longs, e outro com um guid. Preencher cada um com N-milhões de linhas. Moniter o desempenho de cada durante as operações de CRUD (criar, ler, atualizar, excluir). Você pode descobrir que ele tem um impacto na performance, mas insignificante.

Servidores frequentemente executados em caixas sem depuração ambientes e outras aplicações ocupando CPU, memória e I / O de disco rígido (especialmente com RAID). Um ambiente de desenvolvimento só lhe dá uma idéia do desempenho.

Você pode debater GUID ou identidade de todo o dia. Eu prefiro o banco de dados para gerar o valor único, com uma identidade. Se você mesclar dados de vários bancos de dados, adicionar outra coluna (para identificar o banco de dados de origem, possivelmente, um tinyint ou smallint) e formar uma chave primária composta.

Se você vai com uma identidade, certifique-se de escolher o tipo de dados direito, com base no número de chaves esperados você vai gerar:

bigint - 8 Bytes - max positive value: 9,223,372,036,854,775,807  
int    - 4 Bytes - max positive value:             2,147,483,647

Note "número de chaves esperados" é diferente do que o número de linhas. Se você adicionar principalmente e manter as linhas, você pode achar que um INT é o suficiente com mais de 2 bilhões de chaves únicas. Aposto que sua mesa não vai ficar tão grande. No entanto, se você tem uma mesa de alto volume onde você guarda adição e remoção de linhas, você remar contagem pode ser baixo, mas você vai passar por chaves rápido. Você deve fazer alguns cálculos para ver como log que seria necessário para percorrer os INTs 2 bilhões de chaves. Se ele não vai usá-los a qualquer momento em breve ir com INT, caso contrário, o dobro do tamanho da chave e ir com BIGINT.

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