MySQL OPTIMIZE toutes les tables?


245

MySQL possède une commande OPTIMIZE TABLE qui peut être utilisée pour récupérer de l'espace inutilisé dans une installation MySQL. Existe-t-il un moyen (commande intégrée ou procédure stockée commune) d'exécuter cette optimisation pour chaque table de l'installation de la base de données et / ou du serveur, ou est-ce quelque chose que vous auriez à écrire vous-même?


11
Attention, cela ne récupérera pas nécessairement de l'espace. Si vous utilisez InnoDB avec un seul fichier (probablement la configuration la plus courante de nos jours) plutôt que des fichiers séparés par table, vous utiliserez toujours la même quantité d'espace disque à la fin. En fait, je l'ai vu utiliser réellement beaucoup plus d'espace disque quand tout a été dit et fait. Avec de grandes tables, la table peut également être verrouillée très longtemps.
jmichalicek

1
OPTIMIZE TABLEétait utile pour MyISAM. Maintenant que ce moteur disparaît, le besoin de OPTIMIZE TABLEdisparaît, en particulier le besoin d'optimiser périodiquement toutes les tables.
Rick James

+1 pour une bonne info rick - mais étant donné les pratiques standard des bases de données du monde réel, je ne serais pas surpris si les anciennes tables MyISAM subsistent pendant une autre décennie
Alan Storm

Réponses:


410

Vous pouvez utiliser mysqlcheckpour ce faire sur la ligne de commande.

Une base de données:

mysqlcheck -o <db_schema_name>

Toutes les bases de données:

mysqlcheck -o --all-databases

recommanderiez-vous que cette commande soit planifiée pour s'exécuter au moins une fois par mois?
Gaia

11
Salut @ Gaia. Pas nécessairement. L'optimisation de toutes les tables sur un calendrier donné n'est pas bénéfique pour tout le monde. Jetez un œil à cet article et lisez les commentaires pour une réflexion beaucoup plus approfondie sur ce sujet que je ne peux en fournir ici: xaprb.com/blog/2010/02/07/…
Ike Walker

18
utilisation simple:mysqlcheck -u [username] -p[password] -o [database name]
M Rostami

38
Veuillez noter que les tables sont verrouillées pendant l'exécution d'OPTIMIZE, ce qui peut prendre un temps considérable si les tables contiennent beaucoup de données. Ainsi, pendant le temps où une table est OPTIMISÉE, aucun nouvel enregistrement ne peut être inséré ou supprimé. Généralement, OPTIMISER toutes les tables d'un système de production ne peut pas être considéré comme une opération triviale.
Werner

2
@ No-Chip vous pouvez optimiser les tables dans le client MySQL en utilisant la OPTIMIZE TABLEcommande: dev.mysql.com/doc/refman/5.5/en/optimize-table.html . Par exemple, optimisez une table comme ceci OPTIMIZE TABLE <your_schema>.<your_table>;:, optimisez toutes les tables dans un schéma donné comme ceci:select concat('OPTIMIZE NO_WRITE_TO_BINLOG TABLE ',table_schema,'.',table_name,';') into outfile '/tmp/optimize_all_tables.sql' from information_schema.tables where table_schema = 'pabeta' and table_type = 'base table'; source /tmp/optimize_all_tables.sql;
Ike Walker

28

J'ai fait ce script "simple":

set @tables_like = null;
set @optimize = null;
set @show_tables = concat("show tables where", ifnull(concat(" `Tables_in_", database(), "` like '", @tables_like, "' and"), ''), " (@optimize:=concat_ws(',',@optimize,`Tables_in_", database() ,"`))");

Prepare `bd` from @show_tables;
EXECUTE `bd`;
DEALLOCATE PREPARE `bd`;

set @optimize := concat('optimize table ', @optimize);
PREPARE `sql` FROM @optimize;
EXECUTE `sql`;
DEALLOCATE PREPARE `sql`;

set @show_tables = null, @optimize = null, @tables_like = null;

Pour l'exécuter, collez-le simplement dans n'importe quel IDE SQL connecté à votre base de données.

Remarque: ce code NE fonctionnera PAS sur phpmyadmin.

Comment ça fonctionne

Il exécute une show tablesinstruction et la stocke dans une instruction préparée. Ensuite, il exécute un optimize tabledans l'ensemble sélectionné.

Vous pouvez contrôler les tables à optimiser en définissant une valeur différente dans la var @tables_like(par exemple:) set @tables_like = '%test%';.


4
Mon environnement d'hébergement partagé n'a pas 'mysqlchk' disponible, donc je pourrais l'exécuter directement à partir d'une session de terminal 'mysql'. Je vous remercie!
funwhilelost

Je vous en prie. J'utilise ce code pour optimiser 50 bases de données et passer le minimum de temps possible. Si vous pensez que je peux améliorer le code de quelque façon que ce soit, allez-y et faites-moi vos suggestions. Je serai heureux d'améliorer ce précieux morceau de code.
Ismael Miguel

Préparez à bdpartir de @b Code d'erreur: 1064. Vous avez une erreur dans votre syntaxe SQL; consultez le manuel qui correspond à votre version de serveur MySQL pour la bonne syntaxe à utiliser près de 'NULL' à la ligne 1
Paul Gregoire

@IsmaelMiguel c'est MySQL, votre réponse utilise la syntaxe TSQL et ne fonctionnera pas avec MySQL.
Phrancis

2
@LorenzoBelfanti Merci de le confirmer. Je suis convaincu que, même après 2 ans, ce code est utile à au moins 10 personnes. C'est une énorme victoire pour moi! Encore une fois merci!
Ismael Miguel

20

L'exemple de script php suivant peut vous aider à optimiser toutes les tables de votre base de données

<?php

dbConnect();

$alltables = mysql_query("SHOW TABLES");

while ($table = mysql_fetch_assoc($alltables))
{
   foreach ($table as $db => $tablename)
   {
       mysql_query("OPTIMIZE TABLE '".$tablename."'")
       or die(mysql_error());

   }
}

?>

7
Sur une base de données avec 200 tables, vous allez exécuter 200 requêtes distinctes en optimisant 1 table à la fois. Vous devez imploser les noms de table en une seule chaîne et donc une seule requête d'optimisation de table est requise.
Dean Marshall

8
Je me demande si l'approche de requête séparée est parfois meilleure. MySQL dit que les tables sont verrouillées pendant que OPTIMIZE TABLE est en cours d'exécution. Ensuite, il semblerait plus judicieux d'optimiser chacun à la fois pour permettre au serveur d'acquérir des verrous pour le minimum de temps. Évidemment, c'est pour un serveur qui reste accessible. Sinon, je pense qu'une seule requête est la meilleure approche.
glarrain

À quoi ressemblerait le script si vous implosiez et transformiez en une seule requête? Merci.
H.Ferrence

8
@Dean L'approche de requête séparée est souvent préférable pour donner une marge de manœuvre pour une application en direct. En fait, j'ajoute généralement un retard (seulement 750 ms environ) à cet effet.
zanlok

15

Effectuez toutes les procédures nécessaires pour réparer toutes les tables dans toutes les bases de données avec un simple script shell:

#!/bin/bash
mysqlcheck --all-databases
mysqlcheck --all-databases -o
mysqlcheck --all-databases --auto-repair
mysqlcheck --all-databases --analyze

11

pour toutes les bases de données:

mysqlcheck -Aos -uuser -p 

Pour une optimisation de base de données:

mysqlcheck -os -uroot -p dbtest3

Du moins pour moi, sous Linux, la commande mysqlcheck -Aosne nécessite pas d'utilisateur + mot de passe.
Zuul

7

Depuis phpMyAdmin et d'autres sources, vous pouvez utiliser:

SET SESSION group_concat_max_len = 99999999;
SELECT GROUP_CONCAT(concat('OPTIMIZE TABLE `', table_name, '`;') SEPARATOR '') AS O
FROM INFORMATION_SCHEMA.TABLES WHERE 
TABLE_TYPE = 'BASE TABLE'
AND table_name!='dual'
AND TABLE_SCHEMA = '<your databasename>'

Ensuite, vous pouvez copier et coller le résultat dans une nouvelle requête ou l'exécuter à partir de votre propre source. Si vous ne voyez pas l'intégralité de la déclaration: façon de voir toute la déclaration dans phpmyadmin


c'était une bonne réponse, mais mon phpmyadmin n'affiche pas la commande entière, juste les premières alors ... triste pour moi, lol.
MonneratRJ

6

Si vous souhaitez analyser, réparer et optimiser toutes les tables de toutes les bases de données de votre serveur MySQL, vous pouvez le faire en une seule fois depuis la ligne de commande. Vous aurez cependant besoin de root pour le faire.

mysqlcheck -u root -p --auto-repair --optimize --all-databases

Une fois que vous avez exécuté cela, vous serez invité à entrer votre mot de passe racine MySQL. Après cela, cela commencera et vous verrez les résultats au fur et à mesure.

Exemple de sortie:

yourdbname1.yourdbtable1       OK
yourdbname2.yourdbtable2       Table is already up to date
yourdbname3.yourdbtable3
note     : Table does not support optimize, doing recreate + analyze instead
status   : OK

etc..
etc...

Repairing tables
yourdbname10.yourdbtable10
warning  : Number of rows changed from 121378 to 81562
status   : OK

Si vous ne connaissez pas le mot de passe root et que vous utilisez WHM, vous pouvez le changer depuis WHM en accédant à: Accueil> Services SQL> MySQL Root Password


5

Depuis la ligne de commande:

mysqlcheck -o <db_name> -u<username> -p

puis tapez le mot de passe


4

Vous pouvez optimiser / vérifier et réparer toutes les tables de base de données, en utilisant le client mysql.

Tout d'abord, vous devriez obtenir toute la liste des tableaux, séparés par ',':

mysql -u[USERNAME] -p[PASSWORD] -Bse 'show tables' [DB_NAME]|xargs|perl -pe 's/ /,/g'

Maintenant, lorsque vous avez toutes les listes de tables à optimiser:

mysql -u[USERNAME] -p[PASSWORD] -Bse 'optimize tables [tables list]' [DB_NAME]

3

Le MySQL Administrator(partie des outils de l'interface graphique MySQL) peut le faire pour vous au niveau de la base de données.

Sélectionnez simplement votre schéma et appuyez sur le Maintenancebouton dans le coin inférieur droit.

Étant donné que les outils GUI ont atteint le statut de fin de vie, ils sont difficiles à trouver sur la page mysql. Je les ai trouvés via Google: http://dev.mysql.com/downloads/gui-tools/5.0.html

Je ne sais pas si le nouveau MySQL Workbench peut le faire aussi.

Et vous pouvez utiliser l' mysqlcheckoutil de ligne de commande qui devrait également pouvoir le faire.


2

Si vous accédez directement à la base de données, vous pouvez écrire la requête suivante:

OPTIMIZE TABLE table1,table2,table3,table4......;

1

Ce script bash acceptera le mot de passe root comme option et l'optimisera un par un, avec une sortie d'état:

#!/bin/bash

if [ -z "$1" ] ; then
  echo
  echo "ERROR: root password Parameter missing."
  exit
fi
MYSQL_USER=root
MYSQL_PASS=$1
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
TBLLIST=""
COMMA=""
SQL="SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE"
SQL="${SQL} table_schema NOT IN ('information_schema','mysql','performance_schema')"
for DBTB in `mysql ${MYSQL_CONN} -ANe"${SQL}"`
do
    echo OPTIMIZE TABLE "${DBTB};"
    SQL="OPTIMIZE TABLE ${DBTB};"
    mysql ${MYSQL_CONN} -ANe"${SQL}"
done

1

Un script bash de démarrage pour répertorier et exécuter un outil sur les bases de données ...

#!/bin/bash

declare -a dbs
unset opt

for each in $(echo "show databases;" | mysql -u root) ;do

        dbs+=($each)

done



echo " The system found [ ${#dbs[@]} ] databases." ;sleep 2
echo
echo "press 1 to run a check"
echo "press 2 to run an optimization"
echo "press 3 to run a repair"
echo "press 4 to run check,repair, and optimization"
echo "press q to quit"
read input

case $input in
        1) opt="-c"
        ;;
        2) opt="-o"
        ;;
        3) opt="-r"
        ;;
        4) opt="--auto-repair -c -o"
        ;;
        *) echo "Quitting Application .."; exit 7
        ;;
esac

[[ -z $opt ]] && exit 7;

echo " running option:  mysqlcheck $opt in 5 seconds  on all Dbs... "; sleep 5

for ((i=0; i<${#dbs[@]}; i++)) ;do
        echo "${dbs[$i]} : "
        mysqlcheck $opt ${dbs[$i]}  -u root
    done

0

mes 2 cents: commencez par le tableau avec la fragmentation la plus élevée

for table in `mysql -sss -e "select concat(table_schema,".",table_name) from information_schema.tables where table_schema not in ('mysql','information_schema','performance_schema') order by data_free desc;"
do
mysql -e "OPTIMIZE TABLE $table;"
done
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.