MySQL OTTIMIZZA tutte le tabelle?


245

MySQL ha un comando OPTIMIZE TABLE che può essere utilizzato per recuperare spazio inutilizzato in un'installazione MySQL. Esiste un modo (comando incorporato o procedura memorizzata comune) per eseguire questa ottimizzazione per ogni tabella nel database e / o nell'installazione del server o è qualcosa che dovresti scrivere tu stesso?


11
Fai attenzione perché questo non recupererà necessariamente spazio. Se stai usando InnoDB con un singolo file (probabilmente la configurazione più comune in questi giorni) piuttosto che file separati per tabella, alla fine utilizzerai comunque la stessa quantità di spazio su disco. In effetti, l'ho visto effettivamente utilizzare molto più spazio su disco quando tutto è stato detto e fatto. Con tavoli di grandi dimensioni, il tavolo può essere bloccato anche per molto tempo.
jmichalicek,

1
OPTIMIZE TABLEè stato utile per MyISAM. Ora che quel motore sta scomparendo, la necessità di OPTIMIZE TABLEsta scomparendo, in particolare la necessità di ottimizzare periodicamente tutte le tabelle.
Rick James,

+1 per una buona informazione - ma date le pratiche standard del database del mondo reale, non sarei sorpreso se le vecchie tabelle MyISAM rimarranno in circolazione per un altro decennio
Alan Storm

Risposte:


410

Puoi usare mysqlcheckper farlo dalla riga di comando.

Un database:

mysqlcheck -o <db_schema_name>

Tutti i database:

mysqlcheck -o --all-databases

consiglieresti di eseguire questo comando almeno una volta al mese?
Gaia,

11
Ciao @Gaia. Non necessariamente. L'ottimizzazione di tutte le tabelle in un determinato programma non è vantaggiosa per tutti. Dai un'occhiata a questo post e leggi i commenti per approfondire molto di più questo argomento di quello che posso fornire in uno spazio limitato qui: xaprb.com/blog/2010/02/07/…
Ike Walker

18
uso semplice:mysqlcheck -u [username] -p[password] -o [database name]
M Rostami,

38
Si noti che le tabelle vengono bloccate durante l'esecuzione di OPTIMIZE, il che può richiedere molto tempo se le tabelle contengono molti dati. Pertanto, durante il periodo in cui una tabella viene OTTIMIZZATA, non è possibile inserire o eliminare nuovi record. In generale, OTTIMIZZARE tutte le tabelle di un sistema di produzione non può essere considerato un'operazione banale.
Werner,

2
@ No-Chip puoi ottimizzare le tabelle nel client MySQL usando il OPTIMIZE TABLEcomando: dev.mysql.com/doc/refman/5.5/en/optimize-table.html . Ad esempio, ottimizza una tabella in questo modo: OPTIMIZE TABLE <your_schema>.<your_table>;ottimizza tutte le tabelle in un determinato schema in questo modo: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

Ho realizzato questo script 'semplice':

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;

Per eseguirlo, è sufficiente incollarlo in qualsiasi IDE SQL collegato al database.

Avviso: questo codice NON funzionerà su phpmyadmin.

Come funziona

Esegue show tablesun'istruzione e la memorizza in un'istruzione preparata. Quindi esegue un optimize tablenel set selezionato.

Puoi controllare quali tabelle ottimizzare ottimizzando un valore diverso nel var @tables_like(ad es set @tables_like = '%test%';.:).


4
Il mio ambiente di hosting condiviso non ha "mysqlchk" disponibile quindi potrei eseguirlo direttamente da una sessione terminale "mysql". Grazie!
funwhilelost

Prego. Uso questo codice per ottimizzare 50 database e trascorrere il minor tempo possibile. Se pensi che posso migliorare il codice in qualsiasi modo, vai avanti e dammi i tuoi suggerimenti. Sarò felice di migliorare questo prezioso pezzo di codice.
Ismael Miguel,

Prepara bdda @b Codice errore: 1064. Hai un errore nella sintassi SQL; controlla il manuale corrispondente alla versione del tuo server MySQL per la sintassi corretta da usare vicino a "NULL" alla riga 1
Paul Gregoire,

@IsmaelMiguel questo è MySQL, la tua risposta utilizza la sintassi TSQL e non funzionerà con MySQL.
Phrancis,

2
@LorenzoBelfanti Grazie per averlo confermato. Sono evidente che, anche dopo 2 anni, questo codice è utile per almeno 10 persone. Questa è una grande vittoria per me! Ancora una volta grazie!
Ismael Miguel,

20

L'esempio php seguente può aiutarti a ottimizzare tutte le tabelle nel tuo database

<?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
Su un database con 200 tabelle eseguirai 200 query separate ottimizzando 1 tabella alla volta. È necessario implodare i nomi delle tabelle in una stringa e pertanto è necessaria solo una query di ottimizzazione delle tabelle.
Decano Marshall,

8
Mi chiedo se l'approccio di query separato a volte sia migliore. MySQL afferma che le tabelle sono bloccate mentre OPTIMIZE TABLE è in esecuzione. Quindi sembrerebbe più saggio ottimizzare ciascuno alla volta per consentire al server di acquisire i blocchi per il tempo minimo. Ovviamente questo è per un server a cui è stato effettuato l'accesso. In caso contrario, penso che una singola query fornisca l'approccio migliore.
Glarrain,

Come sarebbe lo script se implodessi e trasformassi in 1 query? Grazie.
H. Ferrence,

8
@Dean L'approccio di query separato è spesso migliore per dare respiro a un'applicazione live. In effetti, di solito aggiungo un ritardo (solo 750ms o giù di lì) proprio per quello scopo.
zanlok,

15

Esegui tutte le procedure necessarie per correggere tutte le tabelle in tutti i database con un semplice script shell:

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

11

per tutti i database:

mysqlcheck -Aos -uuser -p 

Per un'ottimizzazione del database:

mysqlcheck -os -uroot -p dbtest3

Almeno per me, sotto Linux, il comando mysqlcheck -Aosnon richiede user + password.
Zuul,

7

Da phpMyAdmin e altre fonti puoi usare:

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>'

Quindi è possibile copiare e incollare il risultato in una nuova query o eseguirlo dalla propria fonte. Se non vedi l'intera affermazione: modo di vedere l'intera affermazione in phpmyadmin


è stata una bella risposta, ma i miei phpmyadmin non mostrano l'intero comando, solo i primi quindi ... triste per me, lol.
MonneratRJ,

6

Se vuoi analizzare, riparare e ottimizzare tutte le tabelle in tutti i database nel tuo server MySQL, puoi farlo in una volta sola dalla riga di comando. Avrai bisogno di root per farlo però.

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

Una volta eseguito, ti verrà richiesto di inserire la password di root di MySQL. Successivamente, inizierà e vedrai i risultati mentre sta accadendo.

Esempio di output:

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

Se non conosci la password di root e stai usando WHM, puoi cambiarla da WHM andando su: Home> Servizi SQL> MySQL Root Password


5

Dalla riga di comando:

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

quindi digitare la password


4

È possibile ottimizzare / controllare e riparare tutte le tabelle del database, utilizzando il client mysql.

Innanzitutto, dovresti ottenere tutto l'elenco delle tabelle, separato da ',':

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

Ora, quando hai tutto l'elenco delle tabelle per l'ottimizzazione:

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

3

La MySQL Administrator(parte degli strumenti della GUI di MySQL) può farlo per te a livello di database.

Basta selezionare lo schema e premere il Maintenancepulsante nell'angolo in basso a destra.

Poiché gli strumenti della GUI hanno raggiunto lo stato di fine vita, sono difficili da trovare nella pagina mysql. Li ho trovati tramite Google: http://dev.mysql.com/downloads/gui-tools/5.0.html

Non so se anche il nuovo MySQL Workbench possa farlo.

E puoi usare lo mysqlcheckstrumento da riga di comando che dovrebbe essere in grado di farlo anche tu .


2

Se si accede direttamente al database, è possibile scrivere la seguente query:

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

1

Questo script bash accetterà la password di root come opzione e la ottimizzerà una per una, con output di stato:

#!/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

Uno script bash di avvio per elencare ed eseguire uno strumento contro i DB ...

#!/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

i miei 2 centesimi: inizia con la tabella con la più alta frammentazione

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.