Meine Anwendung hängt davon ab, dass für bestimmte Tabellen "Spalten anzeigen" ausgeführt wird. Die Ausführung dauert ungefähr 60 ms, während alle anderen Abfragen weniger als eine ms dauern. Das information_schema
direkte Abfragen ist noch langsamer.
Die Datenbank enthält ungefähr 250 Datenbanken mit 100 bis 200 Tabellen pro Datenbank (insgesamt ungefähr 20.000 Tabellen).
- Wie kann ich herausfinden, warum diese Vorgänge so langsam sind?
- Gibt es vielleicht eine Einstellung, die ich ändern kann, um sie schneller laufen zu lassen oder um sie SQL-seitig zwischenzuspeichern?
(Die Anwendung führt ungefähr 14 solcher Abfragen pro Seitenladevorgang durch. Ich bin mir bewusst, dass dieser Legacy-Code bereinigt werden muss, suche aber nach möglichen Optionen, während ich an der langfristigen Korrektur arbeite.)
Antworten:
MySQL berechnet Tabellenstatistiken für bestimmte Vorgänge neu, die auf
INFORMATION_SCHEMA
Tabellen zugreifen (diesSHOW COLUMNS
ist nur ein praktischer Alias für die AbfrageINFORMATION_SCHEMA.COLUMNS
). Setzen Sie innodb_stats_on_metadata auf false, um zu verhindern, dass diese Neuberechnung erfolgt, wenn Sie Metadaten aus der Tabelle anfordern .und fügen Sie Folgendes hinzu
my.cnf
quelle
[mysqld]
dort. Für viele mag es offensichtlich sein, dass diese Einstellung unter mysqld fällt, aber für diejenigen, die diese Frage stellen würden, ist dies möglicherweise nicht offensichtlich. Übrigens beschleunigte sich diesSELECT COUNT(*)
auf einem meinerinformation_schema
Tische von über einer Minute auf 6 Sekunden. Immer noch langsam, aber eine enorme Verbesserung.Ich schlage vor, Sie erstellen eine Datenbank, die die
INFORMATION_SCHEMA
Tabellen (oder nur die, die Sie benötigen) als Replikate enthält. Indizieren Sie sie entsprechend und Sie erhalten Leistungsgewinn.Das Problem der Synchronisierung zwischen dieser Datenbank und
INFORMATION_SCHEMA
ist jedoch schwierig.Sie könnten eine Prozedur haben, die diese Tabellen jede Stunde oder alle 5 Minuten synchronisiert (wie oft wird die Tabellenstruktur geändert?).
Eine andere Idee wäre, MySQL Proxy zu verwenden, um alle
ALTER TABLE
Anweisungen (undCREATE
undDROP
undCREATE INDEX
alle anderen Anweisungen, die die benötigten Informationen ändern) abzufangen und das replizierte Informationsschema zu synchronisieren, nachdem diese Anweisungen erfolgreich waren.Wenn Sie nur die Spaltennamen und keine anderen Informationen wie Datentyp, Länge oder verfügbare Indizes benötigen, können Sie die Verwendung von möglicherweise durch
SHOW COLUMNS
(schnelle) Abfragen ersetzen, die nur 1 Zeile zurückgeben, mitLIMIT 1
oder gar keiner, mit entwederLIMIT 0
oder:Trotz der allgemeinen Ratschläge gegen die Verwendung von
SELECT *
kann dies ein legitimer Fall sein, in dem nichts anderes nützlich ist. (Alles andere*
kann zu Fehlern führen!)quelle
In diesem speziellen Fall denke ich, dass
INFORMATION_SCHEMA
es sich um einen roten Hering handelt. Nach meinen eigenenSHOW COLUMNS
Leistungstestsinnodb_stats_on_metadata
scheint die Variable weder für MyISAM- noch für InnoDB-Tabellen einen Unterschied zu machen.Aus dem MySQL 5.0 Handbuch ...
Dies scheint ab MySQL 5.5 aus dem Handbuch entfernt worden zu sein, scheint aber in dieser Version immer noch zu gelten ...
Die Feldinformationen mit einem Abfrageergebnis zurückgegeben enthalten die gleichen Informationen wie zurück durch
SHOW COLUMNS
, so dass eineSELECT * FROM my_table LIMIT 0
dasselbe zu erreichen , soll eine On-Disk temporäre Tabelle ohne die Erstellung pro Abfrage.Ein kurzes Beispiel, um einfach die Feldnamen in PHP zu erfassen ...
Das Abrufen von Feldinformationen auf diese Weise ist etwas umständlicher zu dekodieren. Sie müssen die Beschreibung der zugrunde liegenden
MYSQL_FIELD
Struktur konsultieren , um die Datentypen und Flags abzurufen, aber sie läuft auf meinem System etwa siebenmal schneller.quelle
Ich mag den ersten Vorschlag in der Antwort von @ yerpcube (+1), aber ich möchte etwas vorschlagen
--no-data
--routines
--triggers
--all-databases
oder--databases
gefolgt von einer Liste der gewünschten DatenbankenDaher sollte mysqldump wie folgt aussehen:
Das ist es. In Zukunft müssen Sie lediglich eine Verbindung zu dieser Datenbankinstanz von Port 3307 herstellen und alle schemabezogenen Abfragen nach Herzenslust ausführen. Sollten Sie eine Tabelle in der Produktionsdatenbank kennen, die sich ändert, mysqldump das Schema aus der Produktion und laden Sie es erneut in die Port 3307-Instanz.
WARNUNG: Wenn Sie eine MySQL-Instanz auf demselben Computer wie die Produktion installieren, stellen Sie unbedingt sicher, dass Sie eine Verbindung zu dieser Instanz herstellen
Wenn Sie ausführen
Es wird die Schlauchproduktion. Also sei vorsichtig !!!!
Eine Alternative wäre, nur einen separaten DB-Server zu verwenden.
quelle