Lohnt sich der Aufwand für die häufige Ungültigmachung des Abfragecaches jemals?

22

Ich arbeite derzeit an einer MySQL-Datenbank, in der eine große Anzahl von Ungültigkeitserklärungen aus dem Abfrage-Cache angezeigt wird, hauptsächlich wegen der hohen Anzahl von INSERT-, DELETE- und UPDATE-Anweisungen, die für viele der Tabellen ausgeführt werden.

Ich versuche festzustellen, ob es überhaupt einen Vorteil gibt, wenn der Abfragecache für SELECT-Anweisungen verwendet wird, die für diese Tabellen ausgeführt werden. Da sie so schnell ungültig werden, scheint es mir das Beste zu sein, SQL_NO_CACHE nur für SELECT-Anweisungen mit diesen Tabellen zu verwenden.

Lohnt sich der Aufwand für häufige Invalidierung jemals?

Bearbeiten: Auf Wunsch des Benutzers @RolandoMySQLDBA unten finden Sie hier die Informationen zu MyISAM und INNODB.

InnoDB

  • Datengröße: 177,414 GB
  • Indexgröße: 114,792 GB
  • Tabellengröße: 292,205 GB

MyISAM

  • Datengröße: 379,762 GB
  • Indexgröße: 80,681 GB
  • Tabellengröße: 460,443 GB

Zusätzliche Information:

  • Version: 5.0.85
  • query_cache_limit: 1048576
  • query_cache_min_res_unit: 4096
  • query_cache_size: 104857600
  • query_cache_type: ON
  • query_cache_wlock_invalidate: OFF
  • innodb_buffer_pool_size: 8841592832
  • 24 GB RAM
Craig Sefton
quelle
2
dom.as/tech/query-cache-tuner fasst es ziemlich gut zusammen
Laurynas Biveinis
Hehe, sehr aufschlussreich.
Craig Sefton

Antworten:

16

Sie sollten den Abfrage-Cache einfach mit deaktivieren

[mysqld]
query_cache_size = 0

und starten Sie mysql neu. Warum sollte ich das vorschlagen ???

Der Abfrage-Cache wird immer mit InnoDB zusammenarbeiten. Es wäre schön, wenn das MVCC von InnoDB die Abfragen aus dem Abfrage-Cache bedienen würde, wenn Änderungen keine Auswirkungen auf wiederholbare Lesevorgänge für andere Transaktionen haben. InnoDB macht das leider nicht. Anscheinend haben Sie viele Anfragen, die ziemlich schnell ungültig werden und wahrscheinlich nicht wiederverwendet werden.

Für InnoDB unter MySQL 4.0 wurde der Abfrage-Cache für Transaktionen deaktiviert. Ab MySQL 4.1 spielt InnoDB Traffic Cop, wenn der Zugriff auf den Abfrage-Cache tabellenweise gewährt wird.

Aus der Perspektive Ihrer Frage würde ich sagen, dass die Rechtfertigung für das Entfernen des Abfragecaches nicht so sehr der Overhead ist, sondern wie InnoDB ihn verwaltet.

Weitere Informationen zur Interaktion von InnoDB mit dem Abfragecache finden Sie auf den Seiten 213-215 des Buches "High Performance MySQL (Second Edition)" .

Wenn alle oder ein Großteil Ihrer Daten MyISAM sind, können Sie mit Ihrer ursprünglichen Idee, SQL_NO_CACHE zu verwenden, fortfahren.

Wenn Sie eine Mischung aus InnoDB und MyISAM haben, müssen Sie das richtige Gleichgewicht für Ihre Anwendung finden, basierend auf der Höhe Ihrer Cache-Fehler. Tatsächlich verweisen die Seiten 209-210 desselben Buches auf Gründe für Cache-Fehler:

  • Die Abfrage kann nicht zwischengespeichert werden, entweder weil sie ein nicht deterministisches Konstrukt enthält (wie CURRENT_DATE) oder weil die Ergebnismenge zu groß zum Speichern ist. Beide Arten von nicht zwischengespeicherten Abfragen erhöhen die Statusvariable Qcache_not_cached.
  • Der Server hat die Abfrage noch nie gesehen, daher hatte er nie die Möglichkeit, das Ergebnis zwischenzuspeichern.
  • Das Ergebnis der Abfrage wurde zuvor zwischengespeichert, aber der Server hat es entfernt. Dies kann vorkommen, weil nicht genügend Arbeitsspeicher vorhanden ist, weil der Server angewiesen wurde, ihn zu entfernen, oder weil er ungültig wurde

und die Hauptursachen für hohe Cache-Fehler mit wenigen nicht zwischenspeicherbaren Abfragen können sein:

  • Der Abfragecache ist noch nicht warm. Das heißt, der Server hatte keine Chance, den Cache mit Ergebnismengen zu füllen.
  • Der Server sieht Abfragen, die er noch nicht gesehen hat. Wenn Sie nicht viele wiederholte Abfragen haben, kann dies auch nach dem Aufwärmen des Caches passieren.
  • Es gibt viele Cache-Invalidierungen.

UPDATE 06.09.2012 10:10 EDT

Wenn Sie Ihre letzten aktualisierten Informationen anzeigen, haben Sie query_cache_limit1048576 (1M) festgelegt. Dies begrenzt jede Ergebnismenge auf 1 Million. Wenn Sie etwas größeres abrufen, wird es einfach nicht zwischengespeichert. Während Sie query_cache_size104857600 (100M) festgelegt haben, sind in einer perfekten Welt nur 100 zwischengespeicherte Ergebnisse zulässig. Wenn Sie Hunderte von Abfragen durchführen, kommt es relativ schnell zu einer Fragmentierung. Sie haben auch 4096 (4 KB) als Ergebnismenge für die Mindestgröße. Leider verfügt mysql über keinen internen Mechanismus zum Defragmentieren des Abfragecaches.

Wenn Sie den Abfrage-Cache haben müssen und über so viel RAM verfügen, können Sie Folgendes ausführen:

SET GLOBAL query_cache_size = 0;
SELECT SLEEP(60);
SET GLOBAL query_cache_size = 1024 * 1024 * 1024;

um den Abfrage-Cache zu leeren. Sie verlieren alle zwischengespeicherten Ergebnisse. Führen Sie diese Zeilen daher außerhalb der Spitzenzeiten aus.

Ich würde auch folgendes vergeben:

  • query_cache_size = 1G
  • query_cache_limit = 8 Millionen

Damit verbleiben 23G RAM. Ich würde folgendes ansprechen:

  • innodb_buffer_pool_size = 12G
  • key_buffer_size = 4G

Das lässt 7G. Dies sollte für Betriebssystem- und DB-Verbindungen ausreichend sein.

Beachten Sie, dass der Schlüsselpuffer nur MyISAM-Indexseiten zwischenspeichert, während der InnoDB-Pufferpool Daten und Indizes zwischenspeichert.

Eine weitere Empfehlung: Aktualisieren Sie auf MySQL 5.5, damit Sie InnoDB für mehrere CPUs und mehrere Threads für Lese- / Schreib-E / A konfigurieren können.

Siehe meine früheren Beiträge zur Verwendung von MySQL 5.5 in Verbindung mit dem Zugriff auf mehrere CPUs für InnoDB

UPDATE 2012-09-06 14:56 EDT

Meine Methode zum Leeren des Abfragecaches ist ziemlich extrem, da sie zwischengespeicherte Daten überflutet und ein völlig anderes RAM-Segment bildet. Wie Sie in Ihrem Kommentar ausgeführt haben FLUSH QUERY CACHE(wie Sie vorgeschlagen haben) oder sogar RESET QUERY CACHEbesser wären. Zur Verdeutlichung, als ich "kein interner Mechanismus" sagte, meinte ich genau das. Die Defragmentierung ist erforderlich und muss manuell durchgeführt werden. Es müsste crontab'd werden .

Wenn Sie DML (INSERTs, UPDATEs, DELETEs) in InnoDB häufiger ausführen als in MyISAM, würde ich sagen, dass Sie den Abfrage-Cache insgesamt entfernen, was ich am Anfang gesagt habe.

RolandoMySQLDBA
quelle
Danke für die Antwort. Ich habe dieses Buch und habe es ausgiebig benutzt. Ich kenne die Gründe, die Sie für Cachefehler nennen, sehr gut, aber wie bereits erwähnt, haben wir bereits festgestellt, dass Cachefehler aufgrund der starken Korrelation zwischen Com_select und Qcache_inserts ein Hauptproblem darstellen. Oh, und die fragliche DB hat eine Mischung aus INNODB und MyISAM.
Craig Sefton
Aktualisiert mit den zusätzlichen Informationen, die Sie angefordert haben. Vielen Dank.
Craig Sefton
Danke für die Antwort, ich freue mich auf den Rest. Eines der Dinge, die wir festgestellt haben, war, dass ungefähr 18% der Abfragen nicht zwischengespeichert wurden, also schätzen Sie auf jeden Fall den Rat bezüglich der Einstellungen. Leider ist die Box nicht dediziert, aber Ihre Empfehlungen sollten helfen. Fragmentierung ist definitiv auch ein Thema. Ich bin immer noch sehr besorgt über die Anzahl der Ungültigkeitserklärungen (im Gegensatz zu Abfragen, die überhaupt nicht zwischengespeichert werden), und bin mir immer noch nicht sicher, ob sich der Aufwand lohnt oder nicht. Schätzen Sie wirklich Ihre Einsicht, vielen Dank.
Craig Sefton
Können Sie in Bezug auf Ihren Kommentar zu "mysql hat keinen internen Mechanismus zum Defragmentieren des Abfragecaches" den Befehl FLUSH QUERY CACHEzum Defragmentieren nicht ausführen ? Siehe: dev.mysql.com/doc/refman/5.0/en/flush.html
Craig Sefton
Meine Antwort wurde aktualisiert ...
RolandoMySQLDBA
3

BAD: query_cache_size = 1G

Warum? Wie lange dauert ein Flush? Das heißt, wenn einige Schreibvorgänge ausgeführt werden, werden alle 1 GB nach Verweisen auf die geänderte Tabelle durchsucht. Je größer die QC, desto langsamer ist diese. Ich empfehle eine Größe von nicht mehr als 50 MB, es sei denn, Ihre Daten ändern sich selten.

Die Qualitätskontrolle ist sowohl für MyISAM als auch für InnoDB mit einem Mehraufwand verbunden. Es nimmt einen globalen Mutex heraus und nimmt ihn zu früh heraus. Dieser Mutex ist ein Grund, warum MySQL nicht mehr als 8 Kerne effektiv nutzen kann.

SQL_NO_CACHE wird erst nach dem Sperren des Mutex bemerkt ! Die einzige Verwendung für dieses Flag ist das Benchmarking.

Häufig ist es besser, den RAM einem anderen Cache zuzuweisen.

Rick James
quelle
2

Ich kann mir einen perfekten Fall dafür vorstellen, und wir haben ihn gründlich getestet und in der Produktion ausgeführt ... Ich nenne ihn die "Überholspur" -Clustering-Strategie:

Wenn Sie mit einem Proxy wie MaxScale eine Lese- / Schreibaufteilung durchführen oder Ihre Anwendung dazu in der Lage ist, können Sie einige der Lesevorgänge für diese selten ungültig gemachten Tabellen nur an Slaves senden, bei denen der Abfragecache aktiviert ist, und den Rest an andere Slaves ausgeschaltet.

Dies tun wir und bearbeiten als Ergebnis 4 Millionen Anrufe pro Minute an den Cluster während unserer Auslastungstests (kein Benchmark ... der eigentliche Deal). Die App wartet in master_pos_wait () auf einige Dinge, sodass sie vom Replikationsthread gedrosselt wird. Obwohl der Status "Warten auf Qcache-Invalidierung bei sehr hohem Durchsatz" angezeigt wird, sind diese Durchsatzraten höher als der gerade Wert des Clusters fähig ohne Qcache.

Dies funktioniert, weil in dem winzigen Abfragecache auf diesen Computern selten etwas Relevantes zum Ungültigmachen vorhanden ist (diese Abfragen sind nur für selten aktualisierte Tabellen relevant). Diese Boxen sind unsere "Überholspur". Für den Rest der Abfragen, die die Anwendung ausführt, müssen sie sich nicht mit Qcache herumschlagen, da sie zu Boxen wechseln, ohne dass diese aktiviert sind.

Christopher McGowan
quelle