Mon application dépend de l'exécution de "afficher les colonnes" pour certaines tables. Il faut environ 60 ms pour s'exécuter, tandis que toutes nos autres requêtes prennent moins d'un ms. L'interrogation information_schema
directe est encore plus lente.
La base de données contient environ 250 bases de données, avec 100 à 200 tables par base de données (environ 20k tables au total).
- Comment savoir pourquoi ces opérations sont si lentes?
- Y a-t-il peut-être un paramètre que je peux changer pour le faire fonctionner plus rapidement ou pour le mettre en cache côté SQL?
(L'application effectue environ 14 requêtes de ce type par chargement de page - je suis bien conscient que ce code hérité doit être nettoyé, mais je recherche des options possibles pendant que je travaille sur le correctif à long terme.)
Réponses:
MySQL recalcule les statistiques des tables pour certaines opérations qui accèdent aux
INFORMATION_SCHEMA
tables (SHOW COLUMNS
n'est qu'un alias pratique pour les requêtesINFORMATION_SCHEMA.COLUMNS
). Définissez innodb_stats_on_metadata sur false, ce qui empêchera ce recalcul de se produire lorsque vous demandez des métadonnées à partir de la table.et ajoutez ce qui suit à
my.cnf
la source
[mysqld]
y avoir mis . Il pourrait être évident pour beaucoup que ce paramètre irait sous mysqld, mais peut ne pas être évident pour ceux qui poseraient cette question. Soit dit en passant, cela a accéléréSELECT COUNT(*)
sur l'une de mesinformation_schema
tables à 6 secondes de plus d'une minute. Toujours lent, mais une énorme amélioration.Je vous suggère de créer une base de données contenant les
INFORMATION_SCHEMA
tables (ou uniquement celles dont vous avez besoin) en tant que répliques. Indexez-les correctement et vous obtiendrez un gain de performances.Le problème de synchronisation entre cette base de données et
INFORMATION_SCHEMA
est cependant délicat.Vous pourriez avoir une procédure qui synchronise ces tables toutes les heures ou toutes les 5 minutes (à quelle fréquence la structure des tables est-elle modifiée?).
Une autre idée serait d'utiliser le proxy MySQL pour intercepter toutes les
ALTER TABLE
instructions (etCREATE
etDROP
etCREATE INDEX
et toutes les autres instructions qui modifient les informations dont vous avez besoin), puis synchroniser le schéma d'informations répliquées après la réussite de ces instructions.Si vous n'avez besoin que des noms de colonne et pas d'autres informations, comme le type de données, la longueur ou les index disponibles, vous pouvez peut-être remplacer l'utilisation de
SHOW COLUMNS
requêtes (rapides) qui renvoient une seule ligne, avecLIMIT 1
ou aucune, avec ouLIMIT 0
ou:Malgré les conseils généraux contre l'utilisation de
SELECT *
, cela peut être un cas légitime où rien d'autre n'est utile. (tout le reste, mais*
peut entraîner une erreur!)la source
Dans ce cas particulier, je pense que
INFORMATION_SCHEMA
c'est un hareng rouge. D'après mes propres tests deSHOW COLUMNS
performances, lainnodb_stats_on_metadata
variable ne semble pas faire de différence sur les tables MyISAM ou InnoDB.Cependant, à partir du manuel MySQL 5.0 ...
Cela semble avoir été supprimé du manuel à partir de MySQL 5.5, mais semble toujours s'appliquer dans cette version ...
Les informations de champ renvoyées avec un jeu de résultats de requête contiennent les mêmes informations que celles renvoyées par
SHOW COLUMNS
, donc aSELECT * FROM my_table LIMIT 0
devrait réaliser la même chose sans créer de table temporaire sur disque par requête.Un exemple rapide pour simplement saisir les noms de champs en PHP ...
La récupération des informations de champ de cette manière est un peu plus difficile à décoder. Vous devrez consulter la description de la
MYSQL_FIELD
structure sous-jacente pour extraire les types de données et les indicateurs, mais cela fonctionne environ 7 fois plus rapidement sur mon système.la source
J'aime la première suggestion dans la réponse de @ yerpcube (+1), mais j'aimerais proposer quelque chose
--no-data
--routines
--triggers
--all-databases
ou--databases
suivi d'une liste de bases de données que vous souhaitezAinsi, votre mysqldump devrait ressembler à ceci:
C'est ça. À l'avenir, tout ce que vous devez faire est de vous connecter à cette instance de base de données du port 3307 et d'exécuter toute requête liée au schéma au contenu de votre cœur. Si vous connaissez une table de la base de données de production qui change, juste mysqldump le schéma de production et rechargez-le à nouveau dans l'instance du port 3307.
AVERTISSEMENT: si vous installez une instance mysql sur la même machine que la production, assurez-vous absolument de vous connecter à cette instance en utilisant
Si vous exécutez
Il arrosera la production. Donc sois prudent !!!!
Une alternative serait d'utiliser simplement un serveur DB séparé.
la source