Uma coisa a considerar é que uma chave primária e um índice de cluster não são a mesma coisa. Uma chave primária é uma restrição e lida com as regras pelas quais os dados permanecem (isto é, integridade dos dados); não tem nada a ver com eficiência / desempenho. Uma Chave Primária exige que a (s) coluna (s) da chave seja (unida) e NÃO NULA (individualmente). Uma PK é aplicada por meio de um índice exclusivo, embora possa ser agrupada ou não agrupada.
Um índice clusterizado é um meio de ordenar fisicamente (ou seja, em disco) os dados na tabela e lidar com o desempenho; não tem nada a ver com integridade de dados. Um índice agrupado podeexige que a (s) coluna (s) chave (s) seja (s) combinada (s), mas não precisa. No entanto, como o Índice de Cluster é a ordem física dos dados, ele precisa identificar cada linha exclusivamente, não importa o quê. Portanto, se você não configurá-lo para exigir exclusividade, ele criará sua própria exclusividade por meio de uma coluna "uniquificador" oculta de 4 bytes. Essa coluna está sempre presente em índices agrupados não exclusivos, mas não ocupa espaço quando os campos-chave são exclusivos (em combinação). Para ver em primeira mão como essa coluna "uniquifier" funciona (tanto no Índice de cluster quanto no efeito de índices não de cluster), consulte este script de teste que publiquei no script PasteBin: T-SQL para testar o tamanho do uniquificador .
Portanto, a principal questão de:
seria mais eficiente adicionar um id
campo de incremento automático e usá-lo em conjunto com company_id
a chave primária ou adicionar sobrecarga desnecessária
está confundindo esses dois conceitos, então eles precisam ser abordados separadamente, embora haja definitivamente alguma sobreposição.
Uma IDENTITY
coluna deve ser adicionada ou seria uma sobrecarga desnecessária?
Se você adicionar uma INT IDENTITY
coluna e usá-la para criar uma PK, assumindo que seria uma PK em cluster, que adiciona 4 bytes a cada linha. Esta coluna é visível e utilizável em consultas. Ele pode ser adicionado a outras tabelas como uma chave estrangeira, embora neste caso particular que não vai acontecer.
Se você não adicionar a INT IDENTITY
coluna, não poderá criar uma PK nesta tabela. No entanto, você ainda pode criar um Índice de Cluster na tabela, desde que não use a UNIQUE
opção Nesse caso, o SQL Server adicionará uma coluna oculta chamada "uniquifier" que se comporta conforme descrito acima. Como a coluna está oculta, ela não pode ser usada em consultas ou como referência para chaves estrangeiras.
No que diz respeito à eficiência, essas opções são praticamente as mesmas. Sim, haverá um pouco menos de espaço ocupado com o Índice de Cluster não exclusivo devido a algumas linhas (aquelas com os valores de chave exclusivos iniciais) IDENTITY
ocuparem 0 bytes, enquanto todas as linhas no / PK ocuparão os 4 bytes. Mas não haverá o suficiente das linhas de 0 byte (especialmente com a pequena quantidade esperada) para notar uma diferença, e muito menos pesar a conveniência de poder usar a ID
coluna nas consultas.
Coluna IDENTIDADE INT ou hash da org_path
coluna computada persistente?
Dado que você não procurará linhas com base em org_path
valores, não faz sentido adicionar a sobrecarga da Coluna Computada Persistida, além da necessidade de calcular esse hash nas consultas, a fim de corresponder à Coluna Computada (essa era minha sugestão original, disponível no histórico de revisões aqui , que foi baseado na redação / detalhes iniciais da questão). Nesse caso específico, a INT IDENTITY
coluna "ID" provavelmente é a melhor.
Ordem da coluna-chave
Dado que a ID
coluna raramente será usada em consultas, e como os dois principais casos de uso são "todas as linhas" ou "todas as linhas de um determinado company_id
", eu criaria o PK company_id, id
. E como isso significa que as linhas não são inseridas seqüencialmente, eu especificaria um FILLFACTOR
de 90. Você também precisará fazer a manutenção regular do índice para reduzir a fragmentação.
Segunda questão
O fato de company_id ser a chave primária em outra tabela tem algum efeito aqui
Não.
Desencadear
Como os org_path
valores em a company_id
são únicos, você ainda deve criar um acionador INSERT, UPDATE
para aplicar isso. No gatilho, faça um IF EXISTS
com uma consulta que provavelmente faz um COUNT(*)
e GROUP BY company_id, org_path
. Se algo for encontrado, emita a ROLLBACK
para cancelar a operação DML e, em seguida, RAISERROR
dizendo que há duplicatas.
Agrupamento
Na minha resposta inicial (com base no texto original / detalhes esparsos da pergunta e disponível no histórico de revisões aqui ), sugeri que fosse possível usar um agrupamento binário (ou seja _BIN2
). Agora que temos uma ideia do que exatamente org_path
é, eu não recomendaria o uso de um agrupamento binário. Uma vez que haverá sinais diacríticos, você não quer fazer uso de equivalências linguísticas.
Por que você precisa de um PK?
Por que não usar o company_id como um índice não clusterizado?
Você disse que a maioria das pesquisas está em todas as entradas ou por company_id
Rarely update
Rarely delete
org_path, esta é a única tabela em que ela existe
A resposta de Martin Smith pode lhe
fornecer o que você precisa. Não estou familiarizado com adicionar automaticamente um exclusivo de número inteiro de 4 bytes.
Talvez esteja faltando alguma coisa, mas se você não tiver outras colunas indexadas, não vejo sentido nesse caso de uso.
Se você está preocupado com DRI, as tabelas devem usar a tabela Empresa como o FK para company_id
fonte
INCLUDE
coluna, mas isso é ainda pior, pois está apenas duplicando a tabela. É verdade que o PK não é necessário; a parte importante é o índice de cluster. Mas uma vez que você tenha a IDENTIDADE, é melhor optar pelo PK. E, por favor consulte o novo link na minha resposta para um passeio-through em Uniquifier 😃