A melhor abordagem para fragmentar tabelas MySQL é não fazer isso, a menos que seja totalmente inevitável.
Quando você está escrevendo um aplicativo, geralmente deseja fazê-lo de uma forma que maximize a velocidade, a velocidade do desenvolvedor. Você otimiza para latência (tempo até a resposta estar pronta) ou rendimento (número de respostas por unidade de tempo) apenas quando necessário.
Você particiona e atribui partições a diferentes hosts (= fragmento) apenas quando a soma de todas essas partições não cabe mais em uma única instância do servidor de banco de dados - a razão para isso ser gravações ou leituras.
O caso de gravação é a) a frequência de gravações está sobrecarregando os discos dos servidores permanentemente ou b) há muitas gravações em andamento, de forma que a replicação fica permanentemente atrasada nesta hierarquia de replicação.
O caso de leitura para fragmentação é quando o tamanho dos dados é tão grande que o conjunto de trabalho deles não cabe mais na memória e as leituras de dados começam a atingir o disco em vez de serem atendidas da memória na maior parte do tempo.
Somente quando você tiver que fragmentar, faça isso.
No momento em que você fragmenta, está pagando por isso de várias maneiras:
Muito do seu SQL não é mais declarativo.
Normalmente, em SQL, você informa ao banco de dados quais dados deseja e deixa para o otimizador transformar essa especificação em um programa de acesso a dados. Isso é uma coisa boa, porque é flexível e porque escrever esses programas de acesso a dados é um trabalho enfadonho que prejudica a velocidade.
Com um ambiente fragmentado, você provavelmente está juntando uma tabela no nó A com os dados no nó B, ou tem uma tabela maior do que um nó, nos nós A e B e está juntando dados dela com os dados que estão nos nós B e C. Você está começando a escrever resoluções de junção baseadas em hash do lado do aplicativo manualmente para resolver isso (ou está reinventando o cluster MySQL), o que significa que você acaba com muito SQL que não é mais declarativo, mas expressa a funcionalidade SQL de uma forma procedural (por exemplo, você está usando instruções SELECT em loops).
Você está incorrendo em muita latência de rede.
Normalmente, uma consulta SQL pode ser resolvida localmente e o otimizador conhece os custos associados aos acessos ao disco local e resolve a consulta de uma forma que minimiza os custos para isso.
Em um ambiente fragmentado, as consultas são resolvidas executando acessos de valor-chave em uma rede para vários nós (esperançosamente com acessos de chave em lote e não pesquisas de chave individuais por viagem de ida e volta) ou empurrando partes da WHERE
cláusula para os nós onde eles podem ser aplicado (isso é chamado de 'pushdown de condição') ou ambos.
Mas, mesmo no melhor dos casos, isso envolve muito mais viagens de ida e volta da rede do que uma situação local, e é mais complicado. Especialmente porque o otimizador MySQL não sabe nada sobre latência de rede (Ok, o cluster MySQL está lentamente ficando melhor nisso, mas para o MySQL vanilla fora do cluster isso ainda é verdade).
Você está perdendo muito poder expressivo do SQL.
Ok, isso provavelmente é menos importante, mas as restrições de chave estrangeira e outros mecanismos SQL para integridade de dados são incapazes de abranger vários fragmentos.
O MySQL não tem API que permite consultas assíncronas em bom estado de funcionamento.
Quando os dados do mesmo tipo residem em vários nós (por exemplo, dados do usuário nos nós A, B e C), as consultas horizontais geralmente precisam ser resolvidas em todos esses nós ("Encontre todas as contas de usuário que não foram conectadas por 90 dias ou mais"). O tempo de acesso aos dados cresce linearmente com o número de nós, a menos que vários nós possam ser solicitados em paralelo e os resultados agregados à medida que chegam ("Mapa-Redução").
A pré-condição para isso é uma API de comunicação assíncrona, que não existe para o MySQL em bom estado de funcionamento. A alternativa são muitas bifurcações e conexões nos processos infantis, que é visitar o mundo do chupar na passagem de temporada.
Depois de iniciar a fragmentação, a estrutura de dados e a topologia de rede tornam-se visíveis como pontos de desempenho para seu aplicativo. Para ter um desempenho razoavelmente bom, seu aplicativo precisa estar ciente dessas coisas, e isso significa que realmente apenas a fragmentação no nível do aplicativo faz sentido.
A questão é mais se você deseja fragmentar automaticamente (determinar qual linha vai para qual nó por meio de hash de chaves primárias, por exemplo) ou se deseja dividir funcionalmente de forma manual ("As tabelas relacionadas à história do usuário xyz vão para este mestre, enquanto as tabelas relacionadas a abc e def vão para esse mestre ").
O sharding funcional tem a vantagem de que, se feito corretamente, é invisível para a maioria dos desenvolvedores na maioria das vezes, porque todas as tabelas relacionadas à sua história de usuário estarão disponíveis localmente. Isso permite que eles ainda se beneficiem do SQL declarativo pelo maior tempo possível e também incorrerá em menos latência de rede porque o número de transferências entre redes é mínimo.
O sharding funcional tem a desvantagem de não permitir que uma única tabela seja maior que uma instância e requer atenção manual de um designer.
O sharding funcional tem a vantagem de ser feito com relativa facilidade em uma base de código existente, com várias alterações que não são muito grandes. http://Booking.com fez isso várias vezes nos últimos anos e funcionou bem para eles.
Tendo dito tudo isso, olhando para sua pergunta, acredito que você está fazendo as perguntas erradas ou estou interpretando mal a sua definição de problema.