Estou projetando uma tabela de itens que (potencialmente) conterá dezenas de milhões de registros. Alguns itens não estarão disponíveis para uso até que sejam "aprovados" pelo administrador. Por "uso", quero dizer que esses itens não serão referenciados em nenhuma outra tabela até que sejam "aprovados". Até 50% dos itens podem ser "não aprovados" a qualquer momento. Os registros podem se tornar "aprovados", mas não vice-versa.
Eu considero duas opções de design:
- uma bandeira pouco
- uma tabela separada de itens "não aprovados" - quando o item é aprovado, ele é movido para a tabela "regular" (a renovação do ID do item não é um problema)
Eu acho que a segunda opção é muito melhor. O sinalizador de bit leva apenas um byte por linha, portanto não é um problema. Porém, se temos um milhão de registros aprovados e um milhão de registros não aprovados na mesma tabela - o tempo de varredura aumenta para operações com registros aprovados.
A pergunta é: devo considerar a primeira opção (sinalizador de bit)? Tem algum benefício na situação descrita?
WHERE status='A'
e uma consultaWHERE status = 'A' AND (... other columns and parameters here...)
, então o índice ainda pode ser usado.Respostas:
Você pode ter os dois lados com vistas particionadas .
Você cria uma tabela subjacente para cada status, imposta por restrições, com valores mutuamente exclusivos. Em seguida, uma visão que une as tabelas subjacentes. A visualização ou cada tabela base pode ser referenciada explicitamente. Se o status de uma linha for UPDATEd através da visualização, o DBMS o excluirá de uma tabela base e a inserirá na correspondente ao novo status. Cada tabela base pode ser indexada independentemente, de acordo com seu padrão de uso. O otimizador resolverá as referências de índice para uma única tabela base correspondente, se puder.
Os benefícios são:
a) índices mais rasos. Faça as contas no fan-out do índice, no entanto. Nessa escala e divididos entre os valores de status, é possível que os índices tenham a mesma profundidade nas tabelas divididas e na tabela combinada.
b) nenhum código de aplicativo precisa ser alterado. Os dados continuam a aparecer como um todo contínuo.
c) novos valores futuros de status podem ser incluídos adicionando uma nova tabela base, com restrições e recriando a visualização.
O custo é todo esse movimento de dados; duas páginas e índices associados são gravados para cada atualização de status. Muito IO para lidar. Esse movimento também causará fragmentação.
fonte
Na verdade, não é tanto assim, considerando o que o SQL Server pode lidar com eficiência. Obviamente, lembro-me de um dos meus trabalhos anteriores, em que uma das maiores tabelas (um sistema de instância única) tinha 2 milhões de linhas, e foi com isso que eu já lidei. Em seguida, o próximo trabalho teve 17 instâncias de produção, com algumas tabelas com centenas de milhões de linhas e que foram agregadas em um Data Warehouse com várias tabelas de fatos com mais de 1 bilhão de linhas. Não me interpretem mal, não estou zombando de dezenas de milhões de linhas, apenas enfatizando que, com um bom modelo de dados e uma indexação adequada (e manutenção de índice), o SQL Server pode lidar muito .
Hmm. Isso não parece certo. A taxa de "aprovar" entradas será metade da taxa de obtenção de novas entradas? Para cada 2 novas entradas, apenas 1 será "aprovado"? No seu exemplo de 2 milhões de linhas e 1 milhão cada para "aprovado" e "não aprovado", alguns anos depois com outros 10 milhões de entradas, você espera 6 milhões cada para "aprovado" e "não aprovado"? Ou será que os 1 milhão de "não aprovados" permanecerão um pouco constantes, de modo que, com 10 milhões de novas entradas, haverá 11 milhões de "aprovados" e ainda 1 milhão de "não aprovados"?
Isso é verdade hoje , mas as coisas mudam com o tempo e, portanto, sempre há a possibilidade de a empresa decidir permitir "não aprovação" ou talvez algum outro status, como "arquivado", etc.
Então, vejamos as opções:
Sinalizador (ou possivelmente
TINYINT
"status")TINYINT
colunaDuas tabelas separadas (uma para "aprovado" e uma para "não aprovado")
IDENTITY
coluna e tabela aprovada tem coluna de ID que é não umIDENTITY
(uma vez que não é necessário lá). Portanto, os valores de ID permanecem consistentes à medida que o registro se move entre as tabelas.Pessoalmente, eu me inclinaria para a única tabela com
StatusID
coluna para começar. Usar duas tabelas parece uma otimização prematura complicada demais. Esse tipo de otimização pode ser discutido se / quando o número de registros estiver em várias centenas de milhões e a indexação não fornecer nenhum ganho de desempenho.fonte