Muitas colunas versus poucas tabelas - em termos de desempenho

12

Sim, estou ciente de que a normalização de dados deve ser minha prioridade (como é).

  1. Eu tenho uma tabela com 65 colunas de armazenamento de dados do veículo com colunas: used_vehicle, color, doors, mileage, pricee assim por diante, no total de 65.
  2. Agora, eu posso dividir isso e ter uma Vehiclemesa, VehicleInterior, VehicleExterior, VehicleTechnical, VehicleExtra(todo o um-para-um com principal Vehicletabela).

Vamos supor que eu tenha cerca de 5 milhões de linhas (veículos).

Com SELECTuma WHEREcláusula: o desempenho será melhor pesquisado (ambos os casos indexados pelo menos em IDs):

  1. Vehicle mesa com 65 colunas ou
  2. Vehicletabela com JOINSem outras quatro tabelas (todas com 5 milhões de linhas) para retornar todos os dados relacionados a Vehicle?

(Conforme o mecanismo do banco de dados, considere o PostgreSQL e / ou MySQL).

Realmente aprecia alguma ideia detalhada que possa ter da sua experiência anterior?

Urim Kurtishi
fonte
11
Uma razão fazer isso (particionamento vertical) é se você tiver consultas que lidar com as colunas VehicleInterior, outras consultas que lidam com colunas de única VehicleTechnical, etc., ou se há muitas linhas / veículos que não têm absolutamente nenhuma informação sobre (por exemplo) VehicleExtrade modo em vez de muitas linhas com lotes de valores nulos em uma tabela de, você tem linhas no resto das tabelas e nenhuma linha emVehicleExtra
ypercubeᵀᴹ

Respostas:

14

Supondo que estamos falando de relacionamentos 1: 1 entre todas as tabelas.

O armazenamento geral é praticamente sempre (substancialmente) mais barato com uma única tabela em vez de várias tabelas no relacionamento 1: 1. Cada linha possui 28 bytes de sobrecarga, além de, normalmente, mais alguns bytes para preenchimento extra. E você precisa armazenar a coluna PK com todas as tabelas. E tenha um índice (redundante) separado em cada uma dessas colunas ... O tamanho importa para o desempenho.

Isso é verdade mesmo se muitas colunas forem NULL na maioria das linhas, porque o armazenamento NULL é muito barato :

Ao recuperar todas as colunas, uma única tabela é substancialmente mais rápida que 5 tabelas juntas. Também é muito mais simples . Pode ser difícil associar cinco tabelas se nem todas as linhas estiverem presentes em todas as tabelas. Com as WHEREcondições direcionadas a uma única tabela, é fácil anexar outras tabelas LEFT JOIN. Não é tão trivial se você tiver predicados em várias tabelas ...

O particionamento vertical ainda pode melhorar o desempenho de determinadas consultas. Por exemplo, se 90% de suas consultas recuperarem as mesmas 5 colunas das 65 disponíveis, isso seria mais rápido com uma tabela mantendo essas 5 colunas.

OTOH, você pode atender a essas consultas em algumas colunas selecionadas com um índice de "cobertura" que permite verificações apenas de índice .

Outro candidato ao particionamento vertical: se você tiver muitas atualizações em apenas algumas colunas, enquanto o resto quase nunca muda. Pode ser consideravelmente mais barato dividir linhas nesse caso, pois o Postgres grava uma nova versão de linha para cada atualização. Há exceções para grandes valores armazenados fora da linha ("TOASTed"). Mais detalhes:

Realmente depende da situação completa. Em caso de dúvida, siga a solução simples de ter uma única tabela, especialmente se ela retrata bem a realidade: no seu exemplo, todos esses são atributos de um carro e fazem sentido juntos.

Erwin Brandstetter
fonte
as atualizações serão raras se nenhuma e a seleção for principalmente para todas as colunas (página de detalhes do veículo) e informações principais (poucas colunas) para a lista de resultados de pesquisa e, de fato, talvez a melhor solução seja duas tabelas: uma com informações principais (poucas colunas ) e a outra tabela com o restante das colunas. Então, neste caso, qual é a sua opinião sobre o sql une-se com, digamos, 5 milhões de linhas - em termos de desempenho? BTW obrigado por seu esforço detalhado
Urim Kurtishi
11
@ octavius: uma única tabela com um índice de várias colunas nas poucas colunas para permitir verificações apenas de índice para a lista de resultados pode ser a melhor rota. (Lembre-se de que a sequência de colunas é importante nos índices btree .) As junções não são tão caras, mas ainda serão mais rápidas sem a junção. O tamanho de armazenamento adicionado e a distribuição de dados para várias tabelas podem ser a maior lentidão (mais páginas de dados para ler para cada consulta).
Erwin Brandstetter
11
Concordo com o comentário de Erwins de que a resposta realmente dependerá da situação completa ou do uso no mundo real. Se você constatou que 90% das consultas estavam em um pequeno subconjunto de dados e o desempenho foi absolutamente primordial, pode ser necessário justificar o esforço extra dividido em várias tabelas. Pessoalmente, eu estaria tentando manter o modelo de dados simples. Além disso, quão rápido é rápido o suficiente? Quanto esforço você faz para salvar esse último milissegundo? Você já tentou simular dados e fazer testes?
precisa saber é o seguinte
@ ErrBrandstetter que você mencionou na sua resposta que a relação é 1: 1. E quanto às relações 1: N?
Slim
Para uma relação 1: N, você precisa de duas tabelas separadas de qualquer maneira. Exceto se você agrupar várias linhas em uma matriz ou tipo de documento. Então depende. Os princípios descritos aqui se aplicam independentemente. Seus padrões de acesso e estratégias de índice podem fazer a diferença. Faça uma nova pergunta se você quiser ser mais específico.
Erwin Brandstetter
0

Uma seleção em uma única tabela deve sempre ser mais rápida. Assim que você encontrar seu veículo, você já terá todos os detalhes.

No entanto, você perde a eficiência da normalização. Por exemplo, se 1 carro tivesse muitos modelos com opções diferentes.

Esta é uma referência db de todos os carros? Ou uma lista de veículos em segunda mão? Haveria muitos exemplos da mesma marca / modelo com as mesmas opções?

Edit: eu deveria qualificar minha resposta como sendo rdbms genéricos em vez de específico para o postgres Adardo a resposta detalhada de @ Erwin específica para o postgres

O senhor jura muito
fonte
2
"Uma seleção em uma única tabela deve sempre ser mais rápida." Por quê?
usar o seguinte comando
vehiclemake e vehiclemodel são tabelas diferentes, portanto a tabela vehicle tem chaves estrangeiras de vehiclemake e vehiclemodel. Eu não acho que a normalização é um problema aqui. Eu entendo que selecionar na tabela única seria mais rápido, no entanto, temos uma situação diferente, como a linha com muitas colunas afetará o desempenho e assim por diante versus tabelas com menos colunas (mas poucas tabelas - 5 delas com junções)
Urim Kurtishi
Desculpe, eu tinha perdido o ponto que marca e modelo já estavam separados. A versão curta é que as junções exigem esforço do mecanismo de banco de dados. Se você usar uma única tabela / linha, obterá tudo em uma única seleção, o que resultaria em menos E / S e sobrecarga para o mecanismo db.
precisa saber é o seguinte