MySQL OTIMIZAR todas as tabelas?


245

O MySQL possui um comando OPTIMIZE TABLE que pode ser usado para recuperar espaço não utilizado em uma instalação do MySQL. Existe uma maneira (comando interno ou procedimento armazenado comum) de executar essa otimização para todas as tabelas no banco de dados e / ou instalação do servidor, ou é algo que você precisaria fazer para criar um script?


11
Tenha cuidado, pois isso não necessariamente recuperará espaço. Se você estiver usando o InnoDB com um único arquivo (provavelmente a configuração mais comum atualmente) em vez de arquivos separados por tabela, você ainda utilizará a mesma quantidade de espaço em disco no final. Na verdade, eu vi que ele realmente usa muito mais espaço em disco quando tudo foi dito e feito. Em mesas grandes, a mesa também pode ficar bloqueada por um período muito longo.
21411 jmichalicek

1
OPTIMIZE TABLEfoi útil para o MyISAM. Agora que esse mecanismo está desaparecendo, a necessidade OPTIMIZE TABLEestá desaparecendo, especialmente a necessidade de otimizar periodicamente todas as tabelas.
Rick James

+1 para obter boas informações rick - mas, dadas as práticas padrão de banco de dados do mundo real, não ficaria surpreso se as tabelas antigas do MyISAM permanecerem por mais uma década
Alan Storm

Respostas:


410

Você pode usar mysqlcheckisso na linha de comando.

Um banco de dados:

mysqlcheck -o <db_schema_name>

Todos os bancos de dados:

mysqlcheck -o --all-databases

você recomendaria que esse comando fosse agendado para execução pelo menos uma vez por mês?
Gaia

11
Olá @Gaia. Não necessariamente. Otimizar todas as tabelas em um determinado agendamento não é benéfico para todos. Dê uma olhada neste post e ler os comentários para muito mais no pensamento aprofundado sobre este assunto do que eu posso fornecer em espaço limitado aqui: xaprb.com/blog/2010/02/07/...
Ike Walker

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

38
Esteja ciente de que as tabelas estão bloqueadas enquanto o OPTIMIZE está sendo executado, o que pode levar um tempo substancial se as tabelas contiverem muitos dados. Portanto, durante o período em que uma tabela está sendo otimizada, nenhum novo registro pode ser inserido ou excluído. Geralmente, otimizar todas as tabelas de um sistema de produção não pode ser considerado uma operação trivial.
Werner

2
@ No-Chip, você pode otimizar tabelas no cliente MySQL usando o OPTIMIZE TABLEcomando: dev.mysql.com/doc/refman/5.5/en/optimize-table.html . Por exemplo, otimizar uma tabela como esta: OPTIMIZE TABLE <your_schema>.<your_table>;, otimizar todas as tabelas em um determinado esquema como este: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

Eu fiz esse script 'simples':

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;

Para executá-lo, basta colá-lo em qualquer IDE SQL conectado ao seu banco de dados.

Nota: este código NÃO funciona no phpmyadmin.

Como funciona

Ele executa uma show tablesdeclaração e a armazena em uma declaração preparada. Em seguida, executa a optimize tableno conjunto selecionado.

Você pode controlar quais tabelas otimizar definindo um valor diferente na var @tables_like(por exemplo :) set @tables_like = '%test%';.


4
Meu ambiente de hospedagem compartilhada não possui o 'mysqlchk' disponível para que eu possa executá-lo diretamente de uma sessão do terminal 'mysql'. Obrigado!
funwhilelost

Você é bem vindo. Eu uso esse código para otimizar 50 bancos de dados e gastar o mínimo de tempo possível. Se você acha que posso melhorar o código de alguma forma, vá em frente e me dê suas sugestões. Ficarei feliz em melhorar esse precioso pedaço de código.
Ismael Miguel

Prepare a bdpartir do @b Código de erro: 1064. Você tem um erro na sintaxe do SQL; verifique o manual que corresponde ao seu servidor MySQL versão para o direito de utilizar sintaxe próximo a 'NULL' at line 1
Paul Gregoire

@IsmaelMiguel, este é o MySQL, sua resposta usa a sintaxe TSQL e não funciona com o MySQL.
Phrancis

2
@LorenzoBelfanti Obrigado por confirmar. Fico feliz que, mesmo após 2 anos, esse código seja útil para, pelo menos, 10 pessoas. Essa é uma grande vitória para mim! Mais uma vez obrigado!
Ismael Miguel

20

O exemplo de script php a seguir pode ajudá-lo a otimizar todas as tabelas em seu banco de dados

<?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
Em um banco de dados com 200 tabelas, você executará 200 consultas separadas, otimizando 1 tabela por vez. Você deve implodir os nomes da tabela em uma sequência e, portanto, apenas uma consulta de tabela otimizada é necessária.
Dean Marshall

8
Gostaria de saber se a abordagem de consulta separada às vezes é melhor. O MySQL diz que as tabelas estão bloqueadas enquanto o OPTIMIZE TABLE está em execução. Então, parece mais sensato otimizar cada um de cada vez para permitir que o servidor adquira bloqueios pelo tempo mínimo. Obviamente, isso é para um servidor que continua sendo acessado. Caso contrário, acho que uma única consulta é a melhor abordagem.
glarrain

Como seria o script se você implodisse e transformasse em uma consulta? Obrigado.
11309 H. Ferrence

8
@ Dean A abordagem de consulta separada geralmente é melhor para dar espaço para um aplicativo ativo. Na verdade, eu normalmente adiciono um atraso (apenas 750ms ou mais) exatamente para esse fim.
zanlok

15

Execute todos os procedimentos necessários para corrigir todas as tabelas em todos os bancos de dados com um simples script de shell:

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

11

para todos os bancos de dados:

mysqlcheck -Aos -uuser -p 

Para uma otimização de banco de dados:

mysqlcheck -os -uroot -p dbtest3

Pelo menos para mim, no Linux, o comando mysqlcheck -Aosnão requer usuário + senha.
Zuul

7

No phpMyAdmin e em outras fontes, você pode usar:

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

Em seguida, você pode copiar e colar o resultado em uma nova consulta ou executá-lo a partir de sua própria fonte. Se você não vir a declaração completa: maneira de ver toda a declaração no phpmyadmin


essa foi uma boa resposta, mas meu phpmyadmin não mostra o comando inteiro, apenas os primeiros então ... tristes para mim, lol.
amigos estão

6

Se você deseja analisar, reparar e otimizar todas as tabelas em todos os bancos de dados em seu servidor MySQL, você pode fazer isso de uma só vez na linha de comando. Você precisará de raiz para fazer isso.

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

Depois de executar isso, você será solicitado a digitar sua senha root do MySQL. Depois disso, ele começará e você verá resultados à medida que está acontecendo.

Exemplo de saída:

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 você não souber a senha raiz e estiver usando o WHM, poderá alterá-la no WHM, acessando: Página inicial> Serviços SQL> Senha raiz do MySQL


5

Na linha de comando:

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

então digite a senha


4

Você pode otimizar / verificar e reparar todas as tabelas do banco de dados, usando o cliente mysql.

Primeiro, você deve obter toda a lista de tabelas, separada por ',':

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

Agora, quando você tiver todas as listas de tabelas para otimização:

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

3

O MySQL Administrator(parte do MySQL GUI Tools) pode fazer isso por você no nível do banco de dados.

Basta selecionar seu esquema e pressionar o Maintenancebotão no canto inferior direito.

Como as Ferramentas da GUI atingiram o status de Fim de vida útil, elas são difíceis de encontrar na página do mysql. Encontrei-os pelo Google: http://dev.mysql.com/downloads/gui-tools/5.0.html

Não sei se o novo MySQL Workbench também pode fazer isso.

E você pode usar a mysqlcheckferramenta de linha de comando que também poderá fazer isso.


2

Se você estiver acessando o banco de dados diretamente, poderá escrever a seguinte consulta:

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

1

Esse script bash aceita a senha root como opção e a otimiza uma a uma, com saída de status:

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

Um script bash inicial para listar e executar uma ferramenta nos DBs ...

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

my 2cents: comece com a tabela com maior fragmentação

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.