MySQL: várias tabelas ou uma tabela com muitas colunas?

124

Portanto, essa é mais uma questão de design.

Eu tenho uma chave primária (digamos o ID do usuário) e tenho toneladas de informações associadas a esse usuário.

Devo ter várias tabelas divididas em categorias de acordo com as informações ou devo ter apenas uma tabela com muitas colunas?

O jeito que eu costumava fazer isso era ter várias tabelas, por exemplo, uma tabela para dados de uso de aplicativos, uma tabela para informações de perfil, uma tabela para tokens de back-end etc. para manter as coisas organizadas.

Recentemente, alguém me disse que é melhor não fazer dessa maneira e ter uma mesa com muitas colunas é bom. O problema é que todas essas colunas têm a mesma chave primária.

Eu sou muito novo no design de banco de dados, então qual abordagem é melhor e quais são os prós e os contras?

Qual é a maneira convencional de fazer isso?

Xavier_Ex
fonte
Para maior clareza, me corrija se eu estiver errado, mas acho que as "múltiplas mesas" pode ser entendido como link / tabela associativa: en.wikipedia.org/wiki/Associative_entity
cellepo
1
Esse banco de dados é necessário para fins analíticos ou para processamento operacional / transacional?
Alexander Radev

Respostas:

112

Sempre que as informações são individuais (cada usuário tem um nome e senha), é provavelmente melhor ter uma tabela, pois reduz o número de junções que o banco de dados precisará fazer para recuperar os resultados. Acho que alguns bancos de dados têm um limite no número de colunas por tabela, mas não me preocuparia em casos normais, e você sempre pode dividi-lo mais tarde, se precisar.

Se os dados forem um para muitos (cada usuário possui milhares de linhas de informações de uso), eles deverão ser divididos em tabelas separadas para reduzir dados duplicados (dados duplicados desperdiçam espaço de armazenamento, espaço em cache e dificulta a manutenção do banco de dados )

Você pode achar interessante o artigo da Wikipedia sobre normalização de banco de dados , pois discute os motivos disso em profundidade:

A normalização do banco de dados é o processo de organização dos campos e tabelas de um banco de dados relacional para minimizar a redundância e a dependência. A normalização geralmente envolve dividir tabelas grandes em tabelas menores (e menos redundantes) e definir relacionamentos entre elas. O objetivo é isolar dados para que adições, exclusões e modificações de um campo possam ser feitas em apenas uma tabela e depois propagadas pelo restante do banco de dados por meio dos relacionamentos definidos.

A desnormalização também é algo importante, pois há casos em que a repetição de dados é melhor (uma vez que reduz a quantidade de trabalho que o banco de dados precisa realizar ao ler os dados). Eu recomendo tornar seus dados o mais normalizados possível para começar e desnormalizar apenas se você estiver ciente de problemas de desempenho em consultas específicas.

Brendan Long
fonte
Obrigado pela sua resposta, então, depois de ler, acho que estava falando sobre a situação de informações individuais, quando um usuário tem muitas colunas individuais.
Xavier_Ex 19/03/12
@Xavier_Ex - Sim, se houver apenas uma coluna por usuário, será mais fácil trabalhar com uma tabela enorme de usuários (e muito mais fácil para o mecanismo de banco de dados otimizar).
Brendan Long
Sua postagem editada fornece informações mais úteis! Tenho uma nova preocupação de que, se algumas das colunas forem atualizadas com frequência, devo colocá-las em tabelas separadas? Por exemplo, a data de nascimento de um usuário nunca será atualizada, mas o token de back-end pode ser invalidado após um período de tempo e exigirá atualizações frequentes. Seria melhor se eu separasse as tabelas dessa maneira para melhorar o desempenho? Agora eu vou ler sobre o wiki que você mencionou :) #
2119 Xavier_Ex
@ Xavier_Ex - eu não recomendaria. Você obtém um desempenho significativamente melhor ao procurar todos os dados necessários em uma tabela (consulte o artigo de desnormalização). As junções são caras porque (1) elas exigem a pesquisa de dados em vários locais, o que pode envolver buscas em um disco giratório, (2) geralmente exigem vários índices e algum tipo de mesclagem e (3) dificultam o planejamento de consultas, o que não leva apenas tempo, mas também aumenta as chances de o otimizador de consultas obter algo errado (e consultas mal otimizadas podem ser muito lentas).
Brendan Long
1
Recentemente, eu me deparei com esse mesmo problema, porque as tabelas do MySQL InnoDB têm um limite de tamanho relativamente pequeno (~ 8000 bytes). Na minha tabela de problemas (dados de formulários de seguro muito longos, mais de 100 colunas), temos várias colunas varchar, todas UTF8. Então, preenchíamos facilmente o limite de ~ 8000 bytes e recebíamos o "erro 139 do mecanismo de armazenamento" o tempo todo. Então tivemos que dividir a mesa. (Testamos com o novo formato Barracuda e ele funcionou sem dividir, mas os servidores de nossos clientes ainda usam o MySQL 5.0).
MV.
12

Uma mesa grande geralmente é uma má escolha. As tabelas relacionadas são para as quais o banco de dados relacional foi projetado para trabalhar. Se você indexar corretamente e souber escrever consultas de alto desempenho, elas terão um bom desempenho.

Quando as tabelas recebem muitas colunas, você pode encontrar problemas com o tamanho real da página em que o banco de dados está armazenando as informações. O registro pode acabar sendo muito grande para a página, no qual você pode não conseguir criar ou atualizar um registro específico que deixa os usuários insatisfeitos ou você (pelo menos no SQL Server) pode receber algum estouro para determinados itens tipos de dados (com um conjunto de regras que você precisa procurar se estiver fazendo isso), mas se muitos registros excederem o tamanho da página, você poderá criar enormes problemas de desempenho. Agora, como o MYSQL lida com as páginas e se você tem um problema quando o tamanho potencial da página fica muito grande é algo que você precisaria procurar na documentação desse banco de dados.

HLGEM
fonte
1
Ah vozes diferentes! O que é sempre ótimo. Obrigado pela sua informação! Vou me certificar de que estou ciente disso quando fizer minhas mesas ... mas não sabia que teria que estar ciente de coisas de baixo nível originalmente.
Xavier_Ex 19/03/12
4

Eu tenho um bom exemplo. Banco de dados excessivamente normalizado com o seguinte conjunto de relacionamentos:

people -> rel_p2staff -> staff

e

people -> rel_p2prosp -> prospects

Onde as pessoas têm nomes e detalhes de pessoas, a equipe possui apenas os detalhes do registro da equipe, os prospectos apenas os detalhes da perspectiva e as tabelas rel são tabelas de relacionamento com chaves estrangeiras de pessoas vinculadas à equipe e prospects.

Esse tipo de design continua para todo o banco de dados.

Agora, para consultar esse conjunto de relações, é sempre uma junção de várias tabelas, às vezes 8 ou mais junções de tabela. Ele tem funcionado bem até meados deste ano, quando começou a ficar muito lento agora que passamos de 40000 registros de pessoas.

A indexação e todos os frutos baixos foram usados ​​no ano passado, todas as consultas são otimizadas com perfeição. Esse é o fim do caminho para o projeto e gerenciamento normalizado específico, que agora aprovou uma reconstrução de todo o aplicativo que depende dele, além da reestruturação do banco de dados, por um período de 6 meses. $$$$ Ouch.

A solução será ter uma relação direta people -> staffepeople -> prospect

Vlad
fonte
Estaria interessado em saber como foi a reconstrução? Você acabou projetando algo semelhante à herança de tabela única em que você era um typeser staffou um prospect?
Coderama
1
Fui com relação direta pessoas -> funcionários e pessoas -> perspectiva, funciona um encanto, fácil de usar, rápido para consultar.
Vlad
4

Me deparei com isso, e como alguém que costumava usar muito o MySQL e depois mudou para o Postgres recentemente, uma das grandes vantagens é que você pode adicionar objetos JSON a um campo no Postgres.

Portanto, se você está nessa situação, não precisa necessariamente decidir entre uma tabela grande com muitas colunas e dividi-la, mas pode mesclar colunas em objetos JSON para reduzi-la. Por exemplo, em vez de o endereço ter 5 colunas, ele pode simplesmente Seja um. Você também pode consultar esse objeto também.

moinhaque
fonte
e o desempenho ao usar o objeto json durante a consulta?
dagalti 27/06/19
1
@dagalti o desempenho é bom para os aplicativos em que o usei. Eu não tenho feito minha própria avaliação comparativa sobre ele, mas isso pode ser de utilidade para você: arangodb.com/2018/02/...
moinhaque
3

faça a si mesmo essas perguntas se você colocar tudo em uma tabela. Você terá várias linhas para esse usuário? Se você precisar atualizar um usuário, deseja manter uma trilha de auditoria? O usuário pode ter mais de uma instância de um elemento de dados? (como número de telefone, por exemplo), você terá um caso em que poderá adicionar um elemento ou conjunto de elementos posteriormente? se você responder sim, provavelmente você deseja ter tabelas filho com relacionamentos de chave estrangeira.

Os profissionais das tabelas pai / filho são a integridade dos dados, o desempenho por meio de índices (sim, você também pode fazê-lo em uma tabela plana) e o IMO é mais fácil de manter, se você precisar adicionar um campo posteriormente, principalmente se for um campo obrigatório.

Contras design é mais difícil, as consultas se tornam um pouco mais complexas

Porém, existem muitos casos em que uma mesa grande e plana será apropriada; portanto, você deve analisar sua situação para decidir.

Brian
fonte
Obrigado por me lembrar! Portanto, no meu caso, eu estava considerando apenas o caso em que todos os usuários não podem ter mais de uma linha, portanto, todos os campos de informações são um para um. Além disso, o usuário não pode ter mais de uma instância do mesmo elemento, pois acredito que o conceito de um elemento não pode existir em mais de um local. Para a terceira pergunta, sim, posso adicionar mais elementos à tabela, mas eles não quebrarão os requisitos mencionados acima. Eu acho que a tabela pai / filho é boa quando quero associar várias linhas a um usuário, mas, neste caso, minha preocupação é que um usuário tenha muitas colunas individuais.
Xavier_Ex 19/03/12
mesmo que todos os elementos sejam atualmente um a um, isso não elimina a necessidade ou o desejo de ter IMO de tabelas pai / filho. Manter um registro dos dados alterados é um uso. carregar objetos preguiçosos é outro. embora haja benefícios para uma única estrutura de tabela, também existem benefícios para os layouts de pais e filhos (embora eu tenha visto pessoas passarem ao extremo com eles também).
19712 Brian
1

Já terminei de fazer algum tipo de design de banco de dados. para mim, depende da dificuldade do sistema com o gerenciamento de banco de dados; Sim, é verdade que só existem dados únicos em um só lugar, mas é realmente difícil fazer consultas com bancos de dados excessivamente normalizados e com muitos registros. Basta combinar os dois esquemas; use uma tabela enorme se achar que terá um grande número de registros difíceis de manter, como facebook, gmail, etc. e usar tabela diferente para um conjunto de registros para um sistema simples ... bem, esta é apenas a minha opinião .. espero que possa ajudar .. basta fazê-lo .. você pode fazê-lo ... :)

Christopher
fonte
1
"use uma tabela enorme se você tiver um grande número de registros." Mas, no Facebook, o Google não armazena os dados do usuário em uma única tabela, eles os separaram de tantas tabelas.
Yami Odymel
0

A maneira convencional de fazer isso seria usar tabelas diferentes como em um esquema em estrela ou em um esquema de floco de neve. No entanto, eu basearia essa estratégia em duas vezes. Acredito na teoria de que os dados deveriam existir apenas em um lugar, pois o esquema que mencionei funcionaria bem. No entanto, também acredito que, para mecanismos de relatório e suítes de BI, uma abordagem colunar seria extremamente benéfica, pois é mais favorável às necessidades de relatórios. Abordagens colunares como as do infobright.org têm enormes ganhos de desempenho e compactação, o que torna o uso de ambas as abordagens incrivelmente útil. Muitas empresas estão começando a perceber que apenas uma arquitetura de banco de dados na organização não suporta toda a gama de suas necessidades. Muitas empresas estão implementando o conceito de ter mais de uma arquitetura de banco de dados.

Craig Trombly
fonte
Obrigado pela informação, mas desculpe, eu não entendo muito bem a sua resposta ... Vou fazer uma pesquisa sobre os dois esquema que você mencionou-se primeiro ...
Xavier_Ex
-4

Eu acho que ter uma única tabela é mais eficaz, mas você deve se certificar de que a tabela esteja organizada de uma maneira que mostre o relacionamento, a tendência e a diferença nas variáveis ​​da mesma linha. por exemplo, se a tabela mostra a idade e as notas dos alunos, você deve organizar a tabela de uma maneira que agradeça ao maior pontuador que seja bem diferenciada com o menor e que a diferença na idade dos alunos seja uniforme.

user8081853
fonte