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.
Fragmentação de nível de aplicativo: dbShards é o único produto que conheço que faz "fragmentação com reconhecimento de aplicativo". Existem alguns bons artigos no site. Apenas por definição, a fragmentação com reconhecimento de aplicativo será mais eficiente. Se um aplicativo souber exatamente para onde ir com uma transação sem ter que procurá-la ou ser redirecionado por um proxy, isso por si só será mais rápido. E a velocidade costuma ser uma das principais preocupações, se não a única, quando alguém está investigando a fragmentação.
Algumas pessoas "fragmentam" com um proxy, mas, a meu ver, isso anula o propósito de fragmentar. Você está apenas usando outro servidor para informar às suas transações onde encontrar os dados ou onde armazená-los. Com a fragmentação por reconhecimento de aplicativo, seu aplicativo sabe onde ir sozinho. Muito mais eficiente.
Este é o mesmo que # 2, na verdade.
fonte
Vários novos projetos neste espaço:
github.com/twitter/gizzard/fonte
Shard-Query é uma solução de fragmentação baseada em OLAP para MySQL. Ele permite que você defina uma combinação de tabelas fragmentadas e não fragmentadas. As tabelas não fragmentadas (como tabelas de pesquisa) podem ser unidas livremente a tabelas fragmentadas, e as tabelas fragmentadas podem ser unidas umas às outras, desde que as tabelas sejam unidas pela chave de fragmento (sem fragmentos cruzados ou junções self que cruzam os limites dos fragmentos). Por ser uma solução OLAP, o Shard-Query geralmente tem tempos de resposta mínimos de 100 ms ou menos, mesmo para consultas simples, portanto, não funcionará para OLTP. O Shard-Query foi projetado para analisar conjuntos de big data em paralelo.
Soluções de fragmentação de OLTP também existem para MySQL. Soluções de código fechado incluem ScaleDB , DBShards . A solução OLTP de código aberto inclui JetPants , Cubrid ou Flock / Gizzard (infraestrutura do Twitter).
fonte
Nível de aplicação, é claro.
A melhor abordagem que já encontrei neste livro
MySQL de alto desempenho http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064
Breve descrição: você pode dividir seus dados em várias partes e armazenar aproximadamente 50 partes em cada servidor. Isso o ajudará a evitar o segundo maior problema de fragmentação - o rebalanceamento. Basta mover alguns deles para o novo servidor e tudo ficará bem :)
Eu recomendo fortemente que você compre e leia a parte "escalonamento do mysql".
fonte
Em 2018, parece haver uma solução nativa do MySql para isso. Na verdade, existem pelo menos 2 - InnoDB Cluster e NDB Cluster (há uma versão comercial e uma versão da comunidade).
Como a maioria das pessoas que usam o MySql Community Edition estão mais familiarizadas com o mecanismo InnoDB, isso é o que deve ser explorado como primeira prioridade. Ele suporta replicação e particionamento / fragmentação fora da caixa e é baseado no roteador MySql para diferentes opções de roteamento / balanceamento de carga.
A sintaxe para a criação de suas tabelas precisaria ser alterada, por exemplo:
(este é apenas um dos quatro tipos de particionamento )
Uma limitação muito importante:
fonte
PARTITION BY HASH(YEAR...)
irá verificar todas as partições se você tiver um intervalo de datas. Que nojo.