Dividindo tabelas no MySQL. Boa prática?

14

Comecei a trabalhar em um projeto existente e o desenvolvedor anterior dividiu uma tabela em 10 tabelas separadas com esquemas idênticos, mas com dados diferentes.

As tabelas ficam assim:

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

A chave primária é um idcampo inteiro . O aplicativo usa um algoritmo de hash ( idmod 10) para saber qual tabela acessar ao fazer pesquisas. Por exemplo id= 10 resultaria em [tableName_0].

Combinadas, as tabelas têm provavelmente 100.000 linhas e a taxa de crescimento é relativamente baixa.

Portanto, minha pergunta é se essa é uma solução viável ou se é uma boa prática em qualquer situação. Minha teoria é pressionar para combiná-los, pois isso facilitará as coisas na medida em que UNIONs, etc. A principal desvantagem é alterar todo o código do aplicativo e se vale a pena a longo prazo.

PinkGrapefruit
fonte

Respostas:

16

Acho que todo mundo está complicando demais isso. O ponto principal aqui é:

Combinadas, as tabelas têm provavelmente 100.000 linhas e a taxa de crescimento é relativamente baixa.

Este é um pedaço de bolo para qualquer RDBMS manipular. Vá com uma tabela, indexe-a corretamente e considere-a um problema resolvido.

Você não precisa considerar o particionamento, seja "caseiro" ou não, até começar a manipular volumes extremamente grandes de dados - pense em bilhões de linhas ou mais.

Nick Chammas
fonte
3

Você pode usar tabelas de mesclagem, porém elas são mais antiquadas das versões 4.x. Dado que seu aplicativo é particionado manualmente, é porque a) você está executando uma versão muito antiga ou b) o desenvolvedor original não estava ciente das partições da tabela.

Em resumo, se você estiver executando o 5.1+, pode deixar o mysql fazer esse particionamento para você. Consulte http://dev.mysql.com/doc/refman/5.1/en/partitioning.html Se você estiver usando o 5.5, verifique esses documentos específicos, pois encontrará algumas diferenças.

Há muitas vantagens em particionar. No entanto, depende realmente do conjunto de dados disponível, dos padrões de acesso e de como ele deve ser indexado. Além disso, lembre-se de que meus comentários a seguir estão no contexto do particionamento do mysql 5+, NÃO das tabelas de mesclagem mysql mais antigas; embora às vezes sejam discutidos em termos de partições.

Alguns exemplos:

  • Balde direto (ou hash) com base na chave de pesquisa acessada com freqüência. Se você está sempre procurando por uma chave primária ou outra chave exclusiva, o mysql pode reduzir o espaço de pesquisa por um fator de quantas partições você possui. Observe, no entanto, que isso pode ser prejudicial se você particionar por uma chave e, em seguida, pesquisar com frequência por outra chave. Se você pesquisar por uma chave, os dados não serão particionados, ele deverá realizar MAIS pesquisas em pesquisas (uma para cada partição, francamente, não sabe onde estão os dados)
  • Considere as situações em que você possui um conjunto temporal de registros que cresce por data e remove periodicamente o mês anterior. Se você estiver particionando por data, poderá simplesmente soltar uma partição que é tão rápida quanto soltar uma tabela, não importa o tamanho. Se você pudesse remover essa tabela por datas, seria necessário emitir uma ou mais consultas DELETE em que cada linha individual é excluída. A desvantagem disso é que o mysql não cria automaticamente novas partições depois que você atinge a data máxima que contabilizou neste cenário; você precisa de scripts de manutenção extras construídos de sua parte para adicionar partições conforme necessário.
  • Se você estiver usando myisam, as verificações e recuperações serão muito mais rápidas. Considere uma tabela 100G de myisam. Se você quiser recuperar uma tabela com falha, precisará de pelo menos 100 G de espaço livre em disco. Se ele foi particionado em 10 partes diferentes de tamanho igual, você precisará apenas de 10G de espaço (e menos memória key_sort_buffer para recuperação rápida); mas precisaria fazer uma iteração para cada partição.

Portanto, em resumo, a abordagem geral das tabelas de particionamento pode oferecer muitos benefícios. No entanto, não é uma bala mágica a ser aplicada às cegas, sem considerar os padrões de acesso e o quão exatamente você está particionando.

Eu poderia imaginar situações em que o particionamento desejado é muito específico do aplicativo e seria mais adequado para ter essa lógica na camada do aplicativo. No entanto, dada sua descrição direta do módulo 10, isso não parece ser o caso.

EDITAR

Ao escrever minha descrição, esqueci que você declarou que sua tabela tem 100K linhas. Sem o esquema completo da sua tabela e com o comprimento médio da linha, é difícil dizer com certeza, mas em geral isso soa de tamanho médio, mesmo para hardware modesto. Ao mesmo tempo, se não estiver causando problemas do jeito que está agora ou no futuro próximo, não gaste tempo e introduza riscos alterando-o.

atxdba
fonte
3

O que o desenvolvedor anterior fez por você foi criado com a própria implementação de partição por hash. O MySQL literalmente suporta isso nativamente no MySQL 5.1:

http://dev.mysql.com/doc/refman/5.1/en/partitioning-hash.html

Não consigo pensar em uma boa razão para implementar sua própria partição por hash, em vez de confiar na versão nativa [1]. Realizar alterações de esquema será um pesadelo.

Eu também raramente recomendo partição por hash (a implementação nativa). Eu acho que seria útil se você pudesse usá-lo para pesquisar paralelamente cada partição de uma só vez (o que o MySQL não fará). Se você precisar pesquisar em várias partições, o esquema que você descreveu geralmente será muito mais lento.

[1] No entanto, para alguns dos outros tipos de particionamento, pode fazer sentido rolar seu próprio particionamento. O MySQL força você a tornar sua chave de partição parte da sua chave primária e de todos os índices exclusivos.

Morgan Tocker
fonte
2

Em resposta à pergunta:

é se é ou não uma solução viável

IMHO, isso parece sobrecarga desnecessária. Você pode simplesmente indexar e particionar uma única tabela corretamente, a menos que haja outras informações não reveladas na descrição.

Em resposta à pergunta:

... se é uma boa prática em qualquer situação

IMHO, sharding vertical pode fazer sentido, dependendo do contexto. Quando vejo isso, geralmente está em algum tipo de formulário de log. Vamos fingir que estamos usando isso para logs do servidor web e queremos particionar por mês. Em vez de alterar uma tabela existente todos os dias, poderíamos criar uma nova tabela todos os dias e registrar linhas nessa tabela.

por exemplo, finja que uma tabela de log da web pode assumir o seguinte formato:

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
host VARCHAR(255),
user_agent VARCHAR(255),
etc...

Sua solução cria tabelas conforme necessário no banco de dados do blog:

weblogs.20120301
weblogs.20120302
weblogs.20120303

etc.

Dessa forma, os dados permanecem mantidos e pesquisáveis. A extração se torna um processo periódico normal. As operações contínuas não são bloqueadas pelas operações em dados mais antigos.

No cenário que você apresentou, você está bloqueado em uma estrutura de qualquer maneira, então por que não usar uma única tabela otimizada para essa finalidade? O armazenamento de linhas baseado em algoritmo parece incompleto e propenso a erros.

randomx
fonte
0

Se uma consulta atingir dados enormes, a divisão dos dados por condições de consulta teria uma melhoria notável do desempenho. Mas essa divisão, como você viu, traz alguns problemas de programação.

Portanto, a pergunta é: essa divisão vale a pena pelo desempenho ou prejudica o desempenho?

Se você possui uma transação que precisa bloquear várias linhas em várias tabelas e há problemas (por exemplo, deadlock ou tempo limite da transação), convém combiná-las em uma única tabela e reescrever o SQL para reparar os problemas.

Quando penso em dividir a tabela, considerava a troca entre ganho de desempenho e complexidade de programação.

Na sua situação, a modificação do código existente pode ser uma solução de longo prazo para facilitar a manutenção do código. Eu sugeriria uma tentativa de meta-programação. Por exemplo, usando StringTemplate para gerar SQL dinamicamente. Eu gosto de gerar SQL a partir do mecanismo de metaprogramação, se a modificação do código existente for muito difícil.

Mike Lue
fonte
0

Quando você precisa armazenar arquivos na tabela, usar essa metodologia ajuda a exportar, reparar e restaurar.

Eu tenho tabelas com> 30 Gb particionadas em 10 tabelas. Essas tabelas têm apenas ID - BLOB e para mim é fácil de manter. E eu uso o MyISAM para salvar o buffer INNODB.

Marcelo Bus
fonte