Alto desempenho do MySQL para muitos SELECTs / INSERTs / UPDATEs / DELETEs

9

Estou criando um módulo no qual todo usuário geralmente obtém um registro em uma tabela por 10 a 300 segundos.

Quando o tempo termina, um registro é excluído. O caso é: haverá muitos usuários e os registros mudarão com muita frequência - como isso afetará o desempenho do aplicativo para esta tabela, porque os registros mudarão com muita frequência e estou me perguntando se o mysql está bem com isso? Como os índices iriam e viriam, os dados são alterados como 200 vezes / segundos para esta tabela específica. Talvez eu esteja escolhendo uma solução ruim para esse tipo de trabalho. Alguma sugestão ?

Obrigado!

Aivaras
fonte
2
Você tentou armazenar dados no memcache e depois liberá-los em uma transação a cada poucos segundos?
3
"dados mudam 200 vezes / segundo para esta tabela em particular" Eu acho que essa linha especifica esses dados devem ser mantidos na memória, o tempo de vida útil para o qual ele persiste é pequeno, então provavelmente não deve ir para o disco?
Os índices vêm e vão? Não consigo pensar em nenhum motivo pelo qual você precise criar e soltar índices com muita frequência.
Barry Brown

Respostas:

3

Uma coisa que deve ser levada em consideração é como o MySQL usa buffers para seus principais mecanismos de armazenamento: InnoDB e MyISAM .

O que está armazenado em cache na memória difere bastante entre esses mecanismos de armazenamento.

O InnoDB armazena em cache as páginas de dados e de índice. Eles são carregados no buffer pool do InnoDB, dimensionado por innodb_buffer_pool_size .

O MyISAM armazena em cache apenas as páginas de índice e elas são carregadas no Key Key (Key Buffer), que é dimensionado por key_buffer_size .

Você deve usar o information_schema.tables para obter os tamanhos de dados e índices ocupados no disco para dimensionar corretamente o InnoDB Buffer Pool e o MyISAM Key Cache corretamente .

Dependendo da quantidade de dados que você possui e de quanto tempo permitirá, você pode aquecer os caches da seguinte maneira:

Para cada mesa TableT

  • ir para cada NDX do índice
  • para cada índice NDX
    • execute SELECT todas as colunas no NDX, pelo menos uma coluna não indexada na TabelaT da TabelaT

Ao fazer isso, você garante que todas as páginas de dados e índices sejam lidas pelo menos uma vez. Eles ficarão no cache. Este conceito é praticado, em parte e em princípio, pela Percona . A Percona construiu esse conceito no mk-slave-prefetch . O que este programa faz é

  • ler logs de retransmissão em um escravo antes do escravo processar o SQL nele
  • pegue uma instrução SQL do log de retransmissão e converta-a em um SELECT utilizando as cláusulas WHERE, GROUP BY e ORDER BY como um guia para escolher índices
  • execute a instrução SELECT que veio do SQL convertido

Isso força o escravo a ter 99,99% dos dados necessários ao escravo para processar o SQL rapidamente. Isso também prepara o escravo no caso de você fazer failover manualmente para o escravo e promovê-lo para um mestre. QUAIS CACHES SÃO APENAS DO MESMO COMO O MESTRE DE QUE VOCÊ FALHOU.

CONCLUSÃO

Nada supera ter caches prontos, dispostos e capazes de serem usados ​​em um ambiente de INSERTS, UPDATEs e DELETEs pesados.

De uma chance !!!

EMBARGO

Com o nascimento de produtos como o memcached, alguns se afastaram da necessidade de executar o ajuste adequado do MySQL. É verdade que muitos sites se beneficiam do aumento na recuperação de dados fornecido pelo controle do comportamento de armazenamento em cache de dados, como os desenvolvedores viram rapidamente com o memcached. Muitos outros sites, apenas trocando os mecanismos de armazenamento ou configurando corretamente o MySQL, obtiveram os mesmos benefícios de desempenho. Antes de desistir do banco de dados e usá-lo estritamente como repositório, aproveite ao máximo o banco de dados. Siga a devida diligência e você poderá se surpreender com o que o MySQL fará por você.

RolandoMySQLDBA
fonte
5

Se essa é uma solução ruim, depende de muitas coisas. Esses dados precisam ser persistentes? Caso contrário, talvez uma solução que simplesmente mantenha esses dados na memória funcione melhor.

"Muitos usuários" não estão realmente ajudando ninguém. O MySQL provavelmente ficará bem se "muito" significar algumas centenas. (Embora, dependendo do que mais seu banco de dados tenha que lidar. Muitos milhares provavelmente também devem funcionar.)

Afinal, não importa muito, se você gravar esses registros para permanecer ou excluí-los após alguns segundos ou minutos. A exclusão faz apenas duas operações em uma. E o MySQL pode com certeza lidar com uma quantidade muito grande de criação e exclusão de registros. Certifique-se de usar um índice simples para encontrar esses registros novamente para exclusão.

Mas, sem números reais e algumas informações sobre o hardware que o servidor de banco de dados usa, isso não pode ser respondido com muita precisão.

O melhor seria escrever um aplicativo pequeno, que simula simplesmente a quantidade de carga que você acha que terá sem realizar muito processamento real, basta soltar muitos registros no servidor, excluí-los e, ao mesmo tempo, executar algumas consultas como a o restante do seu programa geraria. Dê uma olhada no seu servidor e veja se isso afeta de alguma forma.

Não tenho certeza, mas existem opções para definir para o MySQL que permitiriam que ele armazenasse em cache uma tabela na memória completamente. Ele faz isso de qualquer maneira em muitas situações e provavelmente você não precisará alterar muito. Mas se você falar sobre uma quantidade realmente muito grande de usuários e registros, poderá ajustar alguns parâmetros para otimizar o cache para suas necessidades especiais.

thorsten müller
fonte
4
+1 por sugerir uma solução que mantenha os dados na memória.
3

Aqui está uma ideia maluca . Envolve suposições e nem sempre as práticas recomendadas (como atualizar uma chave) - receberei muitos negativos por sugerir isso, mas aqui vai ...

Supondo que você tenha um volume muito alto de linhas e alto volume de exclusões, você pode aprimorar o desempenho da exclusão criando 2 partições na sua tabela. As partições diferem pelo primeiro dígito da chave. Exemplo:

O valor da chave 1123234441 é para linhas ativas e o valor da chave: 9123234441 é para linhas inativas (o primeiro dígito neste exemplo é usado da seguinte maneira: 1 = ativo, 9 = inativo).

Agora, quando o usuário exclui uma linha, você não a exclui fisicamente, atualiza a chave (Ai!), Isso moveria automaticamente a linha para a partição de linhas inativas.

Obviamente, você precisa restringir suas seleções para ler dados apenas da partição ativa. Agora, a parte interessante é que a eliminação da partição de linhas inativas é extremamente rápida.

Como eu disse anteriormente, isso funciona se você tiver apenas 1 tabela. Eu não testei isso, por isso é apenas uma abordagem teórica, mas experimentei a velocidade de queda da partição e é surpreendentemente rápido.

Para aprimorar suas seleções, use a indexação adequada e, para aprimorar as inserções, minimize o tamanho da linha e o número de índices (essa instrução é muito genérica ...)

Para uma referência, consulte: http://dev.mysql.com/doc/refman/5.1/en/partitioning-types.html Espero que isso ajude.

NoChance
fonte
2
Não tenho certeza, se isso faz sentido para esse problema específico (meu palpite ainda é que o mysql armazenará em cache a coisa toda e provavelmente esses registros nunca verão um disco). Mas +1 por apontar uma técnica interessante de otimização que eu ainda não conhecia.