(Isto foi sugerido para ser repost aqui do StackOverflow)
Atualmente tem uma tabela .. e precisa começar a adicionar novas colunas de dados a ela. Nem todo registro (mesmo avançando com novos dados após adicionar as novas colunas de dados) terá dados. Portanto, estou me perguntando se isso é mais adequado para uma nova tabela, pois é realmente uma extensão de algumas das linhas de dados e não se aplica a todas as linhas.
Em outras palavras, como haverá muitas colunas não utilizadas para esses novos elementos de dados, parece que isso seria mais adequado para uma nova tabela?
A primeira tabela é um registro de visualizações de página (atualmente 2 milhões de registros)
- Eu iria - Endereço de IP - vezes visto - created_at carimbo de data/hora - encontro
para cada endereço IP, um registro é feito por dia - e visualizações de página consecutivas são adicionadas às visualizações por dia
campo(s) adicional(is) seria(ão) para rastreamento de ponto de origem (ou seja, origem/mídia/campanha do Google Analytics)
Nem toda visita terá essa informação. Presumo que cerca de 10% das linhas terão os dados (já que geralmente são atribuídos apenas na primeira visita)
O principal uso dos dados seria atribuir de onde as pessoas vieram. Isso pode acabar sendo usado com mais frequência (o que parece se prestar à tabela única)
Agradeço o feedback - pode adicionar mais, se necessário
O que você está lutando é com o particionamento vertical. Esta é uma técnica de design de banco de dados físico para melhorar o desempenho. Como acontece com qualquer técnica de design de banco de dados físico, sua aplicabilidade depende das consultas específicas que você está tentando otimizar e se essa técnica as otimizará. De um ponto de vista lógico, se esses novos campos dependem da chave candidata para sua entidade, eles são fatos sobre ela que pertencem a ela. Primeiro, você deve certificar-se de entender completamente a dependência funcional desses novos campos em suas chaves candidatas para verificar se eles realmente são fatos sobre exibições de página diárias. Se estiverem, decidir particioná-los em outra tabela é uma otimização de desempenho que só deve ser feita se atingir suas metas de desempenho.
Em geral, o particionamento vertical é útil se você for consultar essas novas colunas com pouca frequência e distintamente das outras colunas na tabela original. Ao colocar essas colunas em outra tabela que compartilha o mesmo PK da tabela existente, você pode consultá-la diretamente quando quiser essas novas colunas e obter uma taxa de transferência muito maior, pois terá muito mais linhas por página no disco para esta nova tabela pois todas as colunas da tabela original não estarão nessas linhas. No entanto, se você sempre consultar essas colunas junto com as colunas na tabela original, uma partição vertical não faria muito sentido, pois você sempre terá que fazer uma junção externa para obtê-las. As páginas das tabelas no disco entram no buffer pool de um DBMS de forma independente, nunca pré-juntadas, e, portanto, essa junção terá que acontecer com cada execução de consulta, mesmo que os dados sejam fixados no pool de buffers. Nesse cenário, torná-las colunas NULLABLE na tabela original permitiria que o mecanismo de armazenamento do DBMS as armazenasse com eficiência quando NULL e eliminasse a necessidade de junção na recuperação.
Parece-me que seu caso de uso é o último e adicioná-los como NULLABLE à sua tabela original é o caminho a percorrer. Mas, como tudo mais no design de banco de dados, depende e, para tomar a decisão certa, você precisa saber sua carga de trabalho esperada e do que depende uma boa escolha. Um bom exemplo de um caso de uso apropriado para particionamento vertical seria um painel de pesquisa de pessoas, onde seu aplicativo tem algumas informações muito raramente preenchidas sobre uma pessoa que alguém pode querer pesquisar, mas raramente o faz. Se você colocar essas informações em uma tabela diferente, terá algumas boas opções de desempenho. Você pode escrever a pesquisa para ter 2 consultas - uma que usa apenas as informações principais sempre preenchidas para pesquisar (como sobrenome ou ssn), e aquele que une externamente as informações pouco preenchidas apenas quando solicitadas para pesquisa. Ou você pode aproveitar o otimizador DBMS se for inteligente o suficiente para reconhecer para um determinado conjunto de variáveis de host que a junção externa não é necessária e não a executará e, portanto, você só precisa criar 1 consulta.
Qual plataforma de DBMS você está usando? A maneira como a plataforma lida com o armazenamento de colunas NULL, otimiza sua consulta, bem como a disponibilidade de suporte a colunas esparsas (o SQL Server tem isso) afetará a decisão. Por fim, eu recomendaria experimentar os dois designs em um ambiente de teste com dados e carga de trabalho de tamanho de produção e ver qual atinge melhor seus objetivos de desempenho.
Pessoalmente, prefiro adicionar colunas à tabela existente. A nova tabela realmente não compra nada:
where newcolumn is not null
torna-se umleft outer join
Na tabela única, significa apenas que o tamanho da linha pode variar de página para página - mas isso não deve afetar muitas das páginas existentes, especialmente se o índice clusterizado estiver em uma coluna crescente monotonicamente (identidade ou data/hora).
Dadas as informações que você forneceu, e com apenas a normalização geral sendo o objetivo, eu provavelmente simplesmente adicionaria colunas anuláveis, mas você não forneceu informações suficientes sobre como os dados serão usados para saber qual a melhor maneira de modelar os dados é.
Dependendo de como você está realmente usando esses dados, você pode querer considerar um modelo de dados diferente. Se você estiver colocando esses dados para relatórios, convém examinar um modelo dimensional, que pode ser mais eficiente para determinados tipos de relatórios - por exemplo, a análise de hora do dia funciona bem com uma divisão de dimensão de data e hora.
Para responder a perguntas analíticas, como "qual é a hora do dia mais popular para visitas de campanhas como X" ou "em que dia de uma campanha vemos mais visitas por hora", uma única coluna de data-time não funcionará muito bem (mas isso pode até ser dividido em um modelo relacional) e há muitos casos em que você pode tratar o endereço IP como uma dimensão (talvez com algum tipo de dado geográfico em um floco de neve).