Cache de consultas do MySQL, SQL complexas consulta
-
25-09-2019 - |
Pergunta
seguinte problema está me dando uma dor de cabeça.
Eu configurei meu servidor MySQL para usar "Consulta Chaching".
set global query_cache_size = 10000000;
parece que o meu cache de consulta funciona, porque a saída de
SHOW STATUS LIKE 'Qcache%';
é o seguinte
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 47223976 |
| Qcache_hits | 6709 |
| Qcache_inserts | 2314 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 365 |
| Qcache_queries_in_cache | 441 |
| Qcache_total_blocks | 960 |
+-------------------------+----------+
mas, nevertheles o seguinte (consulta complexa, com interior seleciona etc.) não fica armazenado em cache.
Ele leva alsways pelo menos 0.8 segundos para obter os dados para esta consulta.Como posso trazer o mysql armazenar os resultados da consulta em cache?
Eu tentei at remover o interior seleciona, mas isso não faz de um differnence.
SELECT p.id
AS
project_id,
p.code
AS project_code,
p.title
AS project_title,
p.start_date
AS project_start_date,
p.end_date
AS project_end_date,
p.modf
AS project_modf,
( p.budget * (SELECT 1 / r.VALUE
FROM exchange_rates r
WHERE r.class_currency_id = p.class_budget_currency_id) )
AS
project_budget,
(SELECT z.txt
FROM sys_labels z
WHERE z.id = ps.value_label_id
AND z.lng = 'en')
AS project_status,
(SELECT z.txt
FROM sys_labels z
WHERE z.id = ps.data_label_id
AND z.lng = 'en')
AS project_color,
GROUP_CONCAT(DISTINCT pt.class_topic_id)
AS projects_thematic_area_ids,
u.id
AS project_owner_id
FROM projects AS p
LEFT JOIN projects_thematic_areas AS pt
ON pt.project_id = p.id
LEFT JOIN sys_users AS u
ON u.id = p.owner_uid
LEFT JOIN class_data s
ON s.id = p.class_status_id
LEFT JOIN class_data AS ps
ON ps.id = s.id
LEFT JOIN sys_labels AS prdz1
ON prdz1.id = prd.value_label_id
AND prdz1.lng = 'en'
LEFT JOIN sys_labels AS prdz2
ON prdz2.id = prd.data_label_id
AND prdz2.lng = 'en'
LEFT JOIN projects_locations AS pl
ON pl.project_id = p.id
LEFT JOIN class_data AS l
ON l.id = pl.class_location_id
LEFT JOIN class_data AS r
ON r._lft <= l._lft
AND r._rgt >= l._rgt
AND r._level = 1
AND r.class_id = 5
LEFT JOIN class_data AS c
ON c._lft <= l._lft
AND c._rgt >= l._rgt
AND c._level = 2
AND c.class_id = 10
LEFT JOIN projects_donors AS pd
ON pd.project_id = p.id
LEFT JOIN institutions AS i
ON pd.inst_id = i.id
LEFT JOIN class_data AS ic
ON ic.id = i.class_country_id
LEFT JOIN projects_deliverables AS d
ON d.project_id = p.id
WHERE 1 = 1
AND p.is_del = "f"
AND p.is_active = "t"
GROUP BY p.id
ORDER BY p.modf DESC,
p.code DESC
Qualquer ajuda apprechiated ....
Matéria
J.
Solução
Além das respostas anteriores: o cache de consulta não será usado, mesmo que a consulta esteja lá se houver alterações em alguma das tabelas selecionadas.
Mas por que você está juntando -se a essas mesas quando não está selecionando nada deles? Além disso, você provavelmente não deve sub-selecionar nada se puder se juntar a ela.
Algo assim selecionaria exatamente o mesmo:
SELECT
p.id AS project_id,
p.code AS project_code,
p.title AS project_title,
p.start_date AS project_start_date,
p.end_date AS project_end_date,
p.modf AS project_modf,
p.budget * (1 / r.VALUE) AS project_budget,
z1.txt AS project_status,
z2.txt AS project_color,
GROUP_CONCAT(DISTINCT pt.class_topic_id) AS projects_thematic_area_ids,
u.id AS project_owner_id
FROM
projects AS p
LEFT JOIN projects_thematic_areas AS pt ON pt.project_id = p.id
LEFT JOIN sys_users AS u ON u.id = p.owner_uid
LEFT JOIN exchange_rates AS r ON r.class_currency_id = p.class_budget_currency_id
LEFT JOIN class_data s ON s.id = p.class_status_id
LEFT JOIN class_data AS ps ON ps.id = s.id
LEFT JOIN sys_labels AS z1 ON z1.id = ps.value_label_id AND z1.lng = 'en'
LEFT JOIN sys_labels AS z2 ON z2.id = ps.data_label_id AND z2.lng = 'en'
WHERE
1
AND p.is_del = "f"
AND p.is_active = "t"
GROUP BY
p.id
ORDER BY
p.modf DESC,
p.code DESC
É claro que você tem índices (combinados) em todas as chaves estrangeiras, onde campos e campos de grupo. Considere usar um campo Tinyint ou enum para seus valores booleanos. Você também pode considerar não selecionar esse grupo_CONCAT para perder o grupo. E talvez usando a junção interna em vez de a partida à esquerda, se você tiver certeza de que a relação existe.
Outras dicas
Você pode tentar SELECT SQL_CACHE ... FROM ...
Algumas coisas básicas que você pode tentar:
- Leia o Cache De Consulta De Documentação para certificar-se de que você compreender os conceitos básicos e ter o programa de configuração correctamente.
- Idealmente isolar o seu banco de dados MySQL server, então é só executar os comandos que você está dando a ele.Se você não pode fazer isso, em seguida, tente a configuração e a execução de testes em outra máquina.
- Executar uma consulta simples e olhar para o
Qcache_hits
eCom_select
variáveis de status para determinar se o cache de consulta está sendo atingido ou não. - Tente a sua consulta complexa e monitorar os mesmos valores.Se a consulta não é bater o cache, em seguida, tente partes menores, até você descobrir o que está causando isso para não entrar em cache.Se está a ser armazenado em cache, então o problema pode ser devido a qualquer uma das tabelas na consulta a ser atualizado entre consultas que invalidaria a cópia em cache.