A sobrecarga da invalidação frequente do cache de consulta vale a pena?

22

Atualmente, estou trabalhando em um banco de dados MySQL, onde estamos vendo um grande número de invalidações do cache de consulta, principalmente devido ao alto número de instruções INSERT, DELETE e UPDATE que estão sendo executadas em muitas das tabelas.

O que estou tentando determinar é se existe ou não algum benefício em permitir que o cache de consulta seja usado para instruções SELECT que estão sendo executadas nessas tabelas. Como eles são invalidados tão rapidamente, parece-me que o melhor seria usar SQL_NO_CACHE nas instruções SELECT com essas tabelas.

Vale a pena a sobrecarga de invalidação frequente?

Edit: A pedido do usuário @RolandoMySQLDBA abaixo, aqui estão as informações sobre MyISAM e INNODB.

InnoDB

  • Tamanho dos dados: 177.414 GB
  • Tamanho do índice: 114.792 GB
  • Tamanho da tabela: 292,205 GB

MyISAM

  • Tamanho dos dados: 379.762 GB
  • Tamanho do índice: 80,681 GB
  • Tamanho da tabela: 460.443 GB

Informação adicional:

  • Versão: 5.0.85
  • query_cache_limit: 1048576
  • query_cache_min_res_unit: 4096
  • query_cache_size: 104857600
  • query_cache_type: ON
  • query_cache_wlock_invalidate: OFF
  • innodb_buffer_pool_size: 8841592832
  • 24 GB de RAM
Craig Sefton
fonte
2
dom.as/tech/query-cache-tuner resume bastante bem #
Laurynas Biveinis
Hehe, muito perspicaz.
Craig Sefton

Respostas:

16

Você deve apenas desativar o cache de consulta com

[mysqld]
query_cache_size = 0

e então reinicie o mysql. Por que eu sugeriria isso ???

O cache de consulta sempre se aproxima do InnoDB. Seria bom se o MVCC do InnoDB permitisse que as consultas fossem atendidas a partir do cache, se as modificações não afetarem leituras repetíveis para outras transações. Infelizmente, o InnoDB simplesmente não faz isso. Aparentemente, você tem muitas consultas que são invalidadas rapidamente e provavelmente não estão sendo reutilizadas.

Para o InnoDB no MySQL 4.0, o cache da consulta foi desativado para transações. Para o MySQL 4.1+, o InnoDB reproduz tráfego policial ao permitir o acesso ao cache de consultas por tabela.

Do ponto de vista da sua pergunta, eu diria que a justificativa para remover o cache da consulta não é tanto a sobrecarga, mas como o InnoDB gerencia.

Para obter mais informações sobre como o InnoDB interage com o cache de consultas, leia as páginas 213-215 do livro "High Performance MySQL (Second Edition)" .

Se todos ou a maioria dos seus dados são MyISAM, você pode seguir sua ideia original de usar SQL_NO_CACHE.

Se você possui uma combinação de InnoDB e MyISAM, terá que encontrar o equilíbrio certo para o seu aplicativo, com base no quão alto o cache está ausente. De fato, as páginas 209-210 do mesmo livro apontam os motivos das falhas de cache:

  • A consulta não é armazenável em cache, porque contém uma construção não determinística (como CURRENT_DATE) ou porque seu conjunto de resultados é muito grande para armazenar. Ambos os tipos de consultas não armazenáveis ​​aumentam a variável de status Qcache_not_cached.
  • O servidor nunca viu a consulta antes, portanto nunca teve a chance de armazenar em cache seu resultado.
  • O resultado da consulta foi armazenado em cache anteriormente, mas o servidor a removeu. Isso pode acontecer porque não há memória suficiente para mantê-lo, porque alguém instruiu o servidor a removê-lo ou porque foi invalidado

e as causas principais de falta de cache alto com poucas consultas incontroláveis ​​podem ser:

  • O cache da consulta ainda não está quente. Ou seja, o servidor não teve a chance de preencher o cache com conjuntos de resultados.
  • O servidor está vendo consultas que não tinha visto antes. Se você não tiver muitas consultas repetidas, isso poderá acontecer mesmo após o aquecimento do cache.
  • Existem muitas invalidações de cache.

UPDATE 2012-09-06 10:10 EDT

Procurando as informações atualizadas mais recentes, você query_cache_limitdefiniu 1048576 (1M). Isso limita qualquer resultado definido para 1M. Se você recuperar algo maior, ele simplesmente não será armazenado em cache. Enquanto você query_cache_sizedefiniu 104857600 (100M), isso permite apenas 100 resultados armazenados em cache em um mundo perfeito. Se você realizar centenas de consultas, a fragmentação ocorrerá rapidamente. Você também tem 4096 (4K) como o conjunto de resultados de tamanho mínimo. Infelizmente, o mysql não possui mecanismo interno para desfragmentar o cache da consulta.

Se você precisa ter o cache de consulta e ter muita RAM, pode executar o seguinte:

SET GLOBAL query_cache_size = 0;
SELECT SLEEP(60);
SET GLOBAL query_cache_size = 1024 * 1024 * 1024;

para limpar o cache da consulta. Como você perde todos os resultados armazenados em cache, execute essas linhas fora do horário de pico.

Eu também atribuiria o seguinte:

  • query_cache_size = 1G
  • query_cache_limit = 8M

Isso deixa 23G de RAM. Eu levantaria o seguinte:

  • innodb_buffer_pool_size = 12G
  • key_buffer_size = 4G

Isso deixa 7G. Isso deve ser adequado para conexões de sistema operacional e banco de dados.

Lembre-se de que o buffer da chave armazena em cache apenas as páginas de índice MyISAM, enquanto o InnoDB Buffer Pool armazena em cache os dados e os índices.

Mais uma recomendação: atualize para o MySQL 5.5 para poder configurar o InnoDB para várias CPUs e vários threads para E / S de leitura / gravação.

Veja minhas postagens anteriores sobre o uso do MySQL 5.5 em conjunto com o acesso a várias CPUs para o InnoDB

UPDATE 2012-09-06 14:56 EDT

Meu método para limpar o cache da consulta é bastante extremo, porque ele armazena dados em cache e forma um segmento completamente diferente da RAM. Como você apontou em seu comentário FLUSH QUERY CACHE(como você sugeriu) ou até RESET QUERY CACHEseria melhor. Para esclarecimento, quando disse "nenhum mecanismo interno", quis dizer exatamente isso. A desfragmentação é necessária e deve ser feita manualmente. Seria necessário crontab'd .

Se você faz DML (INSERTs, UPDATEs, DELETEs) no InnoDB com mais frequência do que no MyISAM, eu diria que remova o cache de consultas completamente, como disse no começo.

RolandoMySQLDBA
fonte
Obrigado pela resposta. Eu tenho esse livro e tenho usado extensivamente; Estou ciente dos motivos que você descreveu para falhas de cache, mas, como mencionei, já identificamos as invalidações de cache como um problema importante devido à forte correlação que estamos vendo entre Com_select e Qcache_inserts. Ah, e o DB em questão tem uma mistura de INNODB e MyISAM.
Craig Sefton
Atualizado com as informações adicionais solicitadas. Obrigado.
Craig Sefton
Obrigado pela resposta, estou ansioso pelo resto. Uma das coisas que identificamos foi que cerca de 18% das consultas não estavam sendo armazenadas em cache; por isso, definitivamente aprecio os conselhos sobre as configurações. Infelizmente, a caixa não é dedicada, mas suas recomendações devem ajudar. A fragmentação é definitivamente um problema também. Ainda estou realmente preocupado com o número de invalidações que estamos vendo (em oposição a consultas que não são armazenadas em cache), por isso ainda estou incerto se a sobrecarga vale a pena ou não. Realmente aprecio sua visão, muito obrigado.
Craig Sefton
Em relação ao seu comentário sobre "o mysql não possui mecanismo interno para desfragmentar o cache da consulta", você não pode executar o comando FLUSH QUERY CACHEpara desfragmentá-lo? Veja: dev.mysql.com/doc/refman/5.0/en/flush.html
Craig Sefton
Atualizei
3

RUIM: query_cache_size = 1G

Por quê? Por causa de quanto tempo levará um flush. Ou seja, quando ocorrer uma gravação, o 1 GB inteiro será verificado para encontrar referências à tabela que foi modificada. Quanto maior o CQ, mais lento será. Eu recomendo um tamanho não superior a 50 milhões, a menos que seus dados raramente sejam alterados.

O QC é um custo adicional para o MyISAM e o InnoDB. Ele pega um Mutex global e sai muito cedo. Esse mutex é um dos motivos pelos quais o MySQL não pode fazer uso efetivo de mais de 8 núcleos.

SQL_NO_CACHE não é notado até depois que o Mutex é bloqueado! O único uso desse sinalizador é para benchmarking.

Muitas vezes, é melhor fornecer a RAM para outro cache.

Rick James
fonte
2

Eu posso pensar em um caso perfeito para isso, e nós testamos minuciosamente e executamos na produção ... Eu chamo de estratégia de cluster "fast lane" :

Se você faz a divisão de leitura e gravação com um proxy como o MaxScale ou seu aplicativo é capaz, você pode enviar algumas das leituras dessas tabelas raramente invalidadas apenas para os escravos que têm o cache de consulta ativado e o restante para outros escravos com ele desligado.

Fazemos isso e lidamos com 4 milhões de chamadas por minuto para o cluster durante nossos testes de carga (não comparando ... o negócio real) como resultado. O aplicativo espera algumas coisas em master_pos_wait (), portanto ele é acelerado pelo encadeamento de replicação e, embora tenhamos visto um status de espera na invalidação do Qcache com uma taxa de transferência muito alta, esses níveis de taxa de transferência são mais altos do que o cluster capaz de sem Qcache.

Isso funciona porque raramente há algo relevante no pequeno cache de consulta nessas máquinas para invalidar (essas consultas são relevantes apenas para tabelas atualizadas com pouca frequência). Essas caixas são a nossa "via rápida". Nas demais consultas que o aplicativo faz, eles não precisam lidar com o Qcache, pois vão para as caixas sem ele ativado.

Christopher McGowan
fonte