Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Abordagens de fragmentação do MySQL?


A melhor abordagem para fragmentar tabelas MySQL é não fazê-lo, a menos que seja totalmente inevitável fazê-lo.

Quando você está escrevendo um aplicativo, geralmente deseja fazê-lo de uma maneira que maximize a velocidade, a velocidade do desenvolvedor. Você otimiza a latência (tempo até que a resposta esteja pronta) ou a taxa de transferência (número de respostas por unidade de tempo) somente quando necessário.

Você particiona e, em seguida, atribui partições a diferentes hosts (=shard) somente 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 é escrita ou leitura.

O caso de gravação é:a) a frequência das gravações está sobrecarregando permanentemente os discos dos servidores ou b) há muitas gravações em andamento, de modo que a replicação fica permanentemente atrasada nessa hierarquia de replicação.

O caso de leitura para fragmentação é quando o tamanho dos dados é tão grande que o conjunto de trabalho 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 maioria das vezes.

Somente quando você tem para fragmentar você fazê-lo.

No momento em que você estilhaça, você está pagando por isso de várias maneiras:

Muito do seu SQL não é mais declarativo.

Normalmente, em SQL você está informando ao banco de dados quais dados deseja e deixa para o otimizador transformar essa especificação em um programa de acesso a dados. Isso é bom, porque é flexível e porque escrever esses programas de acesso a dados é um trabalho chato que prejudica a velocidade.

Com um ambiente fragmentado, você provavelmente está unindo uma tabela no nó A em relação aos dados no nó B, ou você tem uma tabela maior que um nó, nos nós A e B, e está unindo dados dela em relação aos dados que estão no nó B e C. Você está começando a escrever manualmente as resoluções de junção baseadas em hash do lado do aplicativo para resolver isso (ou está reinventando o cluster MySQL), o que significa que você acaba com muito SQL que não é mais declarativo, mas está expressando a funcionalidade SQL de maneira processual (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 forma a minimizar 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 (esperamos com acessos de chave em lote e não pesquisas de chave individuais por ida e volta) ou enviando partes do WHERE cláusula para os nós onde eles podem ser aplicados (que é chamado de 'empilhamento 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á melhorando lentamente nisso, mas para o MySQL baunilha 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 possui API que permite consultas assíncronas que estejam funcionando.

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 ("Encontrar 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 ("Map-Reduce").

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 é muita bifurcação e conexões nos processos da criança, que é visitar o mundo da sucção em um passe 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 apenas o sharding no nível do aplicativo faz sentido.

A questão é mais se você deseja fragmentar automaticamente (determinando qual linha vai para qual nó por meio de hash de chaves primárias, por exemplo) ou se deseja dividir funcionalmente de maneira manual ("As tabelas relacionadas à história do usuário xyz vão para este master, enquanto as tabelas relacionadas abc e def vão para esse master").

O sharding funcional tem a vantagem de que, se feito corretamente, fica 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ão em menos latência de rede porque o número de transferências entre redes é mínimo.

A fragmentação 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.

A fragmentação funcional tem a vantagem de ser feita 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 entendendo completamente mal a sua declaração do problema.