MySQL Query Cache, komplexe SQL-Abfrage
-
25-09-2019 - |
Frage
folgendes Problem gibt mir Kopfschmerzen.
Ich habe meinen MySQL-Server verwenden "Query chaching" eingerichtet.
set global query_cache_size = 10000000;
Es scheint, dass meine Abfrage-Cache funktioniert, weil die Ausgabe von
SHOW STATUS LIKE 'Qcache%';
wird folgendermaßen als
+-------------------------+----------+
| 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 |
+-------------------------+----------+
aber, nevertheles die folgende (komplexe Abfrage, mit inneren wählt etc.) nicht im Cache erhalten.
Es dauert alsways mindestens 0,8 sec , um die Daten zu dieser Abfrage abzurufen. Wie kann ich bringen mysql speichern Sie die Ergebnisse dieser Abfrage in seiner Cache
Ich habe versucht, die inneren wählt ot zu entfernen, aber dies hat keinen differnence machen.
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
Jede Hilfe apprechiated ....
Viele Grüße
J.
Lösung
Neben den bisherigen Antworten. Die Abfrage-Cache verwendet wird, nicht einmal, wenn die Abfrage ist da drin, wenn es Veränderungen in eines der ausgewählten Tabellen
Aber warum schließen Sie sich al diese Tabellen, wenn Sie nichts Auswahl von ihnen sind? Auch sollten Sie wahrscheinlich nicht sub-select nichts, wenn man kann es kommen.
So etwas würde wählen genau das gleiche:
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
Natürlich haben Sie (kombiniert) Indizes für alle Fremdschlüssel, wo die Felder und Gruppenfelder. Betrachten wir ein tinyint oder Enum Feld für Ihre boolean-Werten. Vielleicht möchten Sie auch nicht, dass GROUP_CONCAT Auswahl, so dass Sie die GROUP BY verlieren können. Und vielleicht mit INNER JOIN statt LEFT JOIN, wenn Sie sicher sind, die Beziehung vorhanden ist.
Andere Tipps
Sie können versuchen SELECT SQL_CACHE ... FROM ...
Vor ein paar grundlegende Dinge, die Sie ausprobieren können:
- Lesen Sie die Query-Cache-Dokumentation , um sicherzustellen, verstehen Sie die Grundlagen und haben Setup es richtig.
- Im Idealfall Ihren MySQL-Datenbank-Server isolieren, so dass es nur die Befehle ausführen Sie ihnen geben. Wenn Sie dies nicht tun können, dann versuchen, den Aufbau und Tests auf einem anderen Rechner läuft.
- Führen Sie eine einfache Abfrage und Blick auf dem
Qcache_hits
undCom_select
Statusvariablen, um zu bestimmen, ob die Abfrage-Cache-Treffer oder nicht zu sein. - Versuchen Sie, Ihre komplexe Abfrage und die gleichen Werte überwachen. Wenn die Abfrage nicht schlagen versuchen, den Cache dann kleinere Teile davon, bis Sie herausfinden, was es verursacht nicht zwischengespeichert zu bekommen. Wenn es dann zwischengespeichert wird das Problem auf eine der Tabellen in der Abfrage zurückzuführen sein kann, zwischen Abfragen aktualisiert werden, die die Cache-Kopie ungültig machen würden.