MySQL Tuning mit Query Cache
Ein unbegründetes Schattendasein fristet in den meisten Distributionen der Query Cache in MySQL. Doch richtig gesetzt bringt dieser einen gehörigen Performance Boost.
Die Funktionsweise erklärt sich am besten, wenn man den Cache einschaltet und die Auswirkungen betrachtet. Es kann dabei nichts passieren, aber wie immer gilt:
Zuerst auf einem Entwicklungssystem testen und dann produktiv einsetzen!
Betrachten wir das System des Query Caches in MySQL.
linux ~ # mysql
mysql> show variables like 'query%';
+------------------------------+---------+
| Variable_name | Value |
+------------------------------+---------+
| query_alloc_block_size | 8192 |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 0 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
| query_prealloc_size | 8192 |
+------------------------------+---------+
Betrachtet man diese Variablen, ist zwar der Cache an (query_cache_type = ON), aber er hat die Größe 0 (query_cache_size = 0). Damit ist der Query Cache dann wieder abgeschalten.
Man schaltet den Cache wie folgt ein:
mysql> set global query_cache_size=1000000;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'query%';
+------------------------------+---------+
| Variable_name | Value |
+------------------------------+---------+
| query_alloc_block_size | 8192 |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 999424 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
| query_prealloc_size | 8192 |
+------------------------------+---------+
Um die Funktionsweise zu überprüfen geht man wie folgt vor.
linux ~ # mysql mysql
mysql> show status like 'qc%';
+-------------------------+--------+
| Variable_name | Value |
+-------------------------+--------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 990760 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 5 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+--------+
mysql> select * from cache_pages;
[...]
6 rows in set (0.06 sec)
mysql> show status like 'qc%';
+-------------------------+--------+
| Variable_name | Value |
+-------------------------+--------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 805368 |
| Qcache_hits | 0 |
| Qcache_inserts | 2 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 6 |
| Qcache_queries_in_cache | 2 |
| Qcache_total_blocks | 7 |
+-------------------------+--------+
Jetzt sieht man mehrere Dinge. Der Wert Qcache_free_memory hat sich verringert (die Abfrage wurde in den Cache geschrieben), der Wert Qcache_queries_in_cache hat sich erhöht (Anzahl der Abfragen im Cache). Jetzt wird die selbe Abfrage nochmals gestartet.
mysql> select * from cache_pages;
[...]
6 rows in set (0.00 sec)
Wichtig dabei ist die Dauer der Abfrage (0.00 sec). Das deutet darauf hin, dass die Abfrage aus dem Cache beantwortet werden konnte. Das sieht man auch an den Status Variablen des Caches.
mysql> show status like 'qc%';
+-------------------------+--------+
| Variable_name | Value |
+-------------------------+--------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 805368 |
| Qcache_hits | 1 |
| Qcache_inserts | 2 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 7 |
| Qcache_queries_in_cache | 2 |
| Qcache_total_blocks | 7 |
+-------------------------+--------+
Die Status Variable QCache_hits hat sich erhöht.
Von dieser zusätzlichen Geschwindigkeit können viele Programme profitieren. Vor allem können Programme davon profitieren, die häufig mit den gleichen Abfragen auf die gleichen Daten lesend zugreifen.
Grenzen des Query Cache
Der Query Cache merkt sich komplette Select Abfragen und deren Ergebnisse. Wenn ein Teil der Abfrage geändert wird, dann greift der Caching Mechanismus nicht.
mysql> show status like 'qc%';
+-------------------------+--------+
| Variable_name | Value |
+-------------------------+--------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 805368 |
| Qcache_hits | 2 |
| Qcache_inserts | 2 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 8 |
| Qcache_queries_in_cache | 2 |
| Qcache_total_blocks | 7 |
+-------------------------+--------+
8 rows in set (0.00 sec)
mysql> select * from cache_pages;
6 rows in set (0.00 sec)
mysql> show status like 'qc%';
+-------------------------+--------+
| Variable_name | Value |
+-------------------------+--------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 805368 |
| Qcache_hits | 3 |
| Qcache_inserts | 2 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 9 |
| Qcache_queries_in_cache | 2 |
| Qcache_total_blocks | 7 |
+-------------------------+--------+
mysql> select * from cache_pages where 1;
[...]
6 rows in set (0.00 sec)
mysql> show status like 'qc%';
+-------------------------+--------+
| Variable_name | Value |
+-------------------------+--------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 630632 |
| Qcache_hits | 3 |
| Qcache_inserts | 3 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 10 |
| Qcache_queries_in_cache | 3 |
| Qcache_total_blocks | 9 |
+-------------------------+--------+
In diesem Beispiel wurde die SQL-Anweisung geringfügig geändert (WHERE 1) und schon greift der Caching Mechanismus nicht mehr (Qcache_hits bleibt gleich und QCache_queries_in_cache erhöht sich).
Wenn die Programmierer dieses bei der Programmierung beachten und häufiger Copy&Paste ihrer SQL-Anweisungen machen, ohne sie zu verändern, kann dieser Mechanismus gut greifen.
Mit der größe des Caches muss man etwas probieren. Sobald der Cache voll ist, werden die am längsten nicht mehr verwendeten Queries aus dem Cache gelöscht (Qcache_lowmem_prunes). Für die meisten Webanwendungen empfiehlt sich ein Wert > 1MB zu setzen.
Um diesen Wert permanent zu setzen (auch nach einem Restart des MySQL Servers) muss dieser Wert noch in die my.cnf des MySQL Servers geschrieben werden.
[mysqld]
[...]
query_cache_size = 1M
Dadurch wird der Wert bei jedem Starten gesetzt. In der Konfigurationsdatei kann man mit den Anhängen k/M... arbeiten, was die Eingabe des Wertes übersichtlicher gestaltet.
:wq