Acabei de começar a mexer com o cache de consulta do nosso CMS.
Alguém pode me dizer (ou pelo menos dar um bom palpite) por que recebo muitoQcache_lowmem_prunes
quando mais da metade é Qcache_free_memory
grátis?
query_cache_size=512M
query_cache_limit=1M
É assim que fica após cerca de 12 horas
show status like '%qcach%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 10338 |
| Qcache_free_memory | 297348320 |
| Qcache_hits | 10254104 |
| Qcache_inserts | 6072945 |
| Qcache_lowmem_prunes | 725279 |
| Qcache_not_cached | 2237603 |
| Qcache_queries_in_cache | 48119 |
| Qcache_total_blocks | 111346 |
+-------------------------+-----------+
Foi assim que ele cuidou flush query cache
;
show status like '%qcach%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 443559256 |
| Qcache_hits | 10307015 |
| Qcache_inserts | 6115890 |
| Qcache_lowmem_prunes | 725279 |
| Qcache_not_cached | 2249405 |
| Qcache_queries_in_cache | 26455 |
| Qcache_total_blocks | 54490 |
+-------------------------+-----------+
O cache de consulta é um recurso muito bom, mas não fique tentado a prestar muita atenção a ele e não fique tentado a torná-lo muito grande. Compreender alguns de seus componentes internos provavelmente ajudará nesse sentido.
O cache de consulta começa como um grande pedaço contíguo de memória disponível. Em seguida, "blocos" são esculpidos neste grande bloco:
O tamanho do bloco é dinâmico, mas o servidor aloca um mínimo de
query_cache_min_res_unit
bytes por bloco, com um padrão típico de 4096 bytes.Sempre que as consultas, os resultados que as acompanham e as referências de tabela são removidos do cache, tornando-se invalidados pela alteração das tabelas subjacentes ou removendo para abrir espaço para consultas mais recentes, isso deixa novos buracos do tamanho de qualquer tamanho desses blocos, e o número de "blocos livres" geralmente aumenta... embora se dois ou mais blocos contíguos forem liberados, o número de "blocos livres" aumentará apenas em 1, e os "blocos livres" não aumentarão se o recém- os blocos liberados são contíguos a um bloco já livre -- o tamanho desse bloco livre apenas se torna maior. Qualquer bloco aberto de memória livre no cache de consulta é contado como 1 bloco livre.
Obviamente, um bloco livre menor que
query_cache_min_res_unit
não será usado.Portanto, os fragmentos do cache de consulta. Se o servidor deseja armazenar em cache uma nova consulta e nenhum bloco livre de tamanho suficiente pode ser organizado (essa descrição é enganosamente simples, porque o algoritmo subjacente é complicado), algo mais deve ser podado ... esse é o seu arquivo
Qcache_lowmem_prunes
. Há um algoritmo "menos usado recentemente" (LRU) que decide o que é removido.Seria sensato perguntar por que o servidor não desfragmenta a memória... mas isso não faria sentido. O cache de consulta ajuda quando pode, mas não é nada estratégico. Você não deseja investir tempo de processamento (especialmente tempo gasto em um bloqueio global) com tarefas de manutenção desnecessárias.
Seria contraproducente para o servidor gastar tempo reorganizando -- desfragmentando -- a memória no cache de consulta, já que os resultados armazenados em cache mudam constantemente e o objetivo do cache é melhorar o desempenho.
O bloqueio global é uma boa razão para você não querer usar um cache de consulta excessivamente grande... .
Mas o
qcache_free_blocks
é essencialmente um indicador de fragmentação do espaço livre. Agora existem muitos blocos não contíguos de memória disponível no cache de consulta. Para que uma nova consulta seja inserida no cache, deve haver um pedaço de espaço livre grande o suficiente para conter a consulta, seus resultados e (às vezes) suas referências de tabela. Se não houver, então alguma outra coisa tem que ir... que é o que você está vendo. Observe, novamente, que o espaço disponível nem sempre precisa ser contíguo (pelo que posso dizer lendo o código-fonte), mas nem todos os buracos serão preenchidos quando houver fragmentação.Mas a fragmentação tende a se nivelar com o tempo, para uma determinada carga de trabalho, já que nada geralmente permanece no cache de consulta pelo tempo esperado.
Isso ocorre porque, de certa forma, o cache de consulta é brilhante em sua simplicidade.
Sempre que os dados em uma tabela referenciada por uma consulta em cache forem alterados, todas as consultas que envolveram essa tabela serão removidas do cache, mesmo que a alteração não afete os resultados armazenados em cache. Isso é verdade mesmo se uma tabela mudar, mas não mudar, como no caso de uma transação InnoDB que é revertida. As entradas do cache de consulta que fazem referência a essa tabela já foram limpas.
Além disso, o cache de consulta é verificado para cada consulta recebida antes que o servidor realmente analise a consulta. A única coisa que corresponderá é outra consulta exatamente a mesma, byte por byte.
SELECT * FROM my_table
eselect * from my_table
não são idênticos byte a byte, portanto, o cache de consulta não percebe que são a mesma consulta.FLUSH QUERY CACHE
não esvazia o cache de consulta. Ele desfragmenta o cache de consulta, e é por isso queQcache_free_blocks
se torna "1". Todo o espaço livre é consolidado.RESET QUERY CACHE
realmente libera (limpa todo o conteúdo) do cache de consulta.FLUSH STATUS
limpa os contadores, mas isso não é algo que você deseja fazer rotineiramente porque zera a maioria das variáveis de status emSHOW STATUS
.Aqui estão algumas demonstrações rápidas.
Linha de base:
Faça uma consulta...
O total de blocos aumentou em 3, inserções em 1 e consultas no cache é 1.
Execute a mesma consulta, mas com letras maiúsculas diferentes...
Esta consulta foi armazenada em cache separadamente. O total de blocos aumentou apenas 2 porque já tínhamos um bloco alocado para a mesa.
Agora, alteramos uma linha diferente na tabela.
Ambas as consultas e a referência da tabela são invalidadas do cache, deixando-nos com 1 bloco livre contíguo, toda a memória cache liberada e todo o espaço livre consolidado em um bloco.
O MySQL não armazenará uma consulta no cache que não seja determinística - como
SELECT NOW();
ou qualquer consulta que você diga especificamente para não armazenar em cache.SELECT SQL_NO_CACHE ...
é a diretiva para dizer ao servidor para não armazenar os resultados no cache. É útil para comparar o tempo real de execução de uma consulta quando o cache está fornecendo uma resposta enganosamente rápida nas execuções subsequentes.