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 idcampo de incremento automático e usá-lo em conjunto com company_ida 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 IDENTITYcoluna deve ser adicionada ou seria uma sobrecarga desnecessária?
Se você adicionar uma INT IDENTITYcoluna 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 IDENTITYcoluna, 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 UNIQUEopçã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) IDENTITYocuparem 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 IDcoluna nas consultas.
Coluna IDENTIDADE INT ou hash da org_pathcoluna computada persistente?
Dado que você não procurará linhas com base em org_pathvalores, 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 IDENTITYcoluna "ID" provavelmente é a melhor.
Ordem da coluna-chave
Dado que a IDcoluna 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 FILLFACTORde 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_pathvalores em a company_idsão únicos, você ainda deve criar um acionador INSERT, UPDATEpara aplicar isso. No gatilho, faça um IF EXISTScom uma consulta que provavelmente faz um COUNT(*)e GROUP BY company_id, org_path. Se algo for encontrado, emita a ROLLBACKpara cancelar a operação DML e, em seguida, RAISERRORdizendo 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.