2010-12-09 6 views
0

folgendes Problem gibt mir Kopfschmerzen.MySQL Query Cache, komplexe SQL-Abfrage

Ich habe meinen MySQL-Server eingerichtet, um "Query Chaching" zu verwenden.

set global query_cache_size = 10000000; 

es scheint, dass meine Abfrage-Cache funktioniert, weil die Ausgabe von

SHOW STATUS LIKE 'Qcache%'; 

wie

folgt ist
+-------------------------+----------+  
| 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.) wird nicht zwischengespeichert.

Es dauert immer mindestens 0,8 Sekunden, um die Daten für diese Abfrage abzurufen. Wie kann ich mysql zu bringen die Ergebnisse dieser Abfrage in den Cache?

Ich habe versucht, die inneren Auswahlen zu entfernen, aber das machte keinen Unterschied.

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 ....

Grüße

J.

Antwort

1

Neben früheren Antworten: Die Abfrage-Cache nicht verwendet werden auch wenn die Abfrage dort ist, wenn Änderungen in einer der ausgewählten Tabellen vorhanden sind.

Aber warum schließen Sie sich diesen Tabellen an, wenn Sie nichts von ihnen auswählen? Außerdem sollten Sie wahrscheinlich nichts auswählen, wenn Sie ihm beitreten können.

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. Verwenden Sie ein Tinyint- oder Enum-Feld für Ihre booleschen Werte. Sie sollten auch in Betracht ziehen, diese GROUP_CONCAT nicht auszuwählen, damit Sie GROUP BY verlieren können. Und vielleicht mit INNER JOIN statt LEFT JOIN, wenn Sie sicher sind, dass die Beziehung existiert.

0

können Sie versuchen, SELECT SQL_CACHE ... FROM ...

0

ein paar grundlegende Dinge, die Sie ausprobieren können:

  • die Query Cache Documentation Lesen Sie die Grundlagen stellen Sie sicher verstehen und richtig eingerichtet es.
  • Im Idealfall isolieren Sie Ihren MySQL-Datenbankserver so, dass er nur die Befehle ausführt, die Sie ihm geben. Wenn dies nicht möglich ist, versuchen Sie, Tests auf einem anderen Computer einzurichten und auszuführen.
  • Führen Sie eine einfache Abfrage aus und sehen Sie sich die Statusvariablen Qcache_hits und Com_select an, um festzustellen, ob der Abfragecache betroffen ist oder nicht.
  • Versuchen Sie Ihre komplexe Abfrage und überwachen Sie die gleichen Werte. Wenn Ihre Abfrage nicht den Cache trifft, versuchen Sie es mit kleineren Teilen, bis Sie herausfinden, was sie verursacht, damit sie nicht zwischengespeichert wird.Wenn es zwischengespeichert wird, kann das Problem dadurch verursacht werden, dass eine der Tabellen in der Abfrage zwischen Abfragen aktualisiert wird, wodurch die zwischengespeicherte Kopie ungültig wird.