Eu tenho grandes tabelas de fatos com índices não clusterizados compostos , algo assim:
NONCLSUTERED INDEX (OrderDate,OrderType,ClientKey,ItemKey,CustomerKey)
As colunas que terminam com "Key" são colunas varchar(50), mas armazenam strings de 20 a 30 caracteres.
Preciso me preocupar a longo prazo, que as colunas varchar no índice realmente variam em comprimento? Terei mais divisões de página, desempenho mais lento quando milhões de linhas se mesclarem nessas tabelas? https://stackoverflow.com/questions/59667/what-are-the-use-cases-for-selecting-char-over-varchar-in-sql
O mecanismo do Sql Server tem mais dificuldade em descobrir o plano usando esse índice, pois as colunas variam em comprimento? Eu li que CHAR é melhor por seu tamanho fixo e é mais fácil para o mecanismo de banco de dados calcular, portanto, ele tem um desempenho melhor. É tão significativo?
Vale a pena fazer o hash dessas colunas "Chave" individualmente com, digamos, a função SHA2_256, para que elas se tornem BINARY(32) de tamanho fixo?
NONCLSUTERED INDEX (OrderDate,OrderType,HASHEDClientKey,HASHEDItemKey,HASHEDCustomerKey)
Eu fiz meu teste para responder pelo menos a pergunta de desempenho e não vejo nenhum benefício de desempenho com hashkeys sobre varchar. Na verdade, é uma grande sobrecarga calcular os hashes e armazenar os 32 bytes extras de cada um ao lado da coluna "Chave" original.
O que não posso testar é como esses índices varchar se comportarão quando eu tiver milhões de linhas mescladas nas tabelas todos os dias?
Qual você escolheria para o ponto de vista de desempenho e manutenção?
Enquanto alguns RDBMSs podem ser ajustados para interagir melhor com strings de comprimento fixo (eu me lembro que talvez o DB2/MVS tenha se saído melhor com strings de tamanho fixo, mas eu aprendi isso em 1996 e era DB2 de mainframe, então não tenho certeza se isso aplicado ao DB2 no Unix ou Windows), eu ficaria chocado se o uso
CHAR(50)
fizesse qualquer coisa além de diminuir o desempenho em comparação com o fato deVARCHAR(50)
que a maioria dos valores está usando apenas 20-30 bytes. UsandoCHAR(50)
ocupa mais espaço, o que reduz o número de linhas que cabem na página de dados, o que aumenta o número de páginas de dados, o que ocupa mais espaço no buffer pool (ou seja, RAM) ao consultar os dados, além de demorar mais para fazer backup e restaurar. E, se não me engano, também aumentará as concessões de memória (ou seja, RAM solicitada por consulta), pois solicitará 50 bytes por campo em vez de 25 (acredito que solicita 50% do tamanho máximo dos campos de comprimento variável). Para uma análise mais detalhada dos efeitos posteriores do uso de mais espaço do que o necessário, consulte: Disk Is Cheap! ORLY? .Dito isto, entre
VARCHAR(50)
eCHAR(50)
, eu escolheria: nem ! Dados os nomes das colunas, estou supondo que essas são realmente dimensões? Filtrar em valores binários/numéricos é muito mais rápido do que filtrar em strings (há uma exceção que mencionarei em breve). Dependendo de quantos valores potenciais haverá ao longo do tempo para clientes, clientes e itens, eu usariaINT
ou, se realmente necessário,BIGINT
como chaves para as dimensões Cliente, Cliente e Item, e armazenaria esses valores de chave numérica aqui .No mínimo , eu mudaria o agrupamento nas
VARCHAR
colunas,Latin1_General_100_BIN2
já que você claramente não está precisando de insensibilidade entre maiúsculas e minúsculas, caso contrário, a ideia de usar um hash SHA-256 nem seria uma opção. Isso deve pelo menos ser capaz de filtrar quase tão rápido quanto umINT
ouBIGINT
(eu digo "quase" apenas devido ao efeito de armazenar valores de 20 a 30 bytes para 3 colunas em vez de valores de 4 ou 8 bytes para essas mesmas 3 colunas , ao contabilizar milhões/bilhões de linhas).Eu desaconselharia fortemente o uso de qualquer tipo de valor de hash aqui. Você não apenas estaria inchando a tabela (ou seja, diminuindo o desempenho), mas perderia qualquer significado desses valores e, portanto, também precisaria armazenar os valores sem hash para essas 3 colunas na tabela de fatos (ou seja, louco) ou exigir uma pesquisa de volta para a tabela de dimensões (nesse caso, você não ganhou nada usando
INT
ouBIGINT
em 4 ou 8 bytes mais nenhuma sobrecarga de cálculo!).