MySQL优化所有表?


245

MySQL有一个OPTIMIZE TABLE命令,该命令可用于回收MySQL安装中未使用的空间。是否有一种方法(内置命令或通用存储过程)为数据库和/或服务器安装中的每个表运行此优化,还是您必须自己编写脚本?


11
请注意,这不一定会回收空间。如果您将InnoDB与单个文件(可能是当今最常见的设置)一起使用,而不是每个表使用单独的文件,则最后仍将使用相同数量的磁盘空间。实际上,当我说完所有内容后,我已经看到它实际上使用了更多的磁盘空间。对于大表,表也可能会锁定很长时间。
jmichalicek 2011年

1
OPTIMIZE TABLE对MyISAM有用。既然该引擎​​即将消失,那么对它的需求OPTIMIZE TABLE就消失了,特别是需要定期优化所有表。
瑞克·詹姆斯

+1表示很好的信息技巧-但考虑到标准的现实世界数据库实践,如果旧的MyISAM表再保留10
Storm

Answers:


410

您可以mysqlcheck在命令行中使用此功能。

一个数据库:

mysqlcheck -o <db_schema_name>

所有数据库:

mysqlcheck -o --all-databases

您是否建议将此命令安排为每月至少运行一次?
盖亚2012年

11
嗨@Gaia。不必要。在给定的时间表上优化所有表并不是对每个人都有利。请看一下这篇文章,并阅读评论,以深入探讨该主题,这比我在有限的空间中所能提供的要多:xaprb.com/blog/2010/02/07/…–
Ike Walker

18
简单易用:mysqlcheck -u [username] -p[password] -o [database name]
M罗斯塔米

38
请注意,在执行OPTIMIZE时,表是锁定的,如果表中包含大量数据,则可能要花费大量时间。因此,在优化表的过程中,不能插入或删除新记录。通常,优化生产系统中的所有表都不能视为微不足道的操作。
2014年

2
@ No-Chip可以使用以下OPTIMIZE TABLE命令在MySQL客户端中优化表:dev.mysql.com/doc/refman/5.5/en/optimize-table.html。例如,优化一个这样的表:OPTIMIZE TABLE <your_schema>.<your_table>;,优化给定架构中的所有表,例如: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

我做了这个“简单”脚本:

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;

要运行它,只需将其粘贴到连接到数据库的任何SQL IDE中。

注意:此代码不适用于phpmyadmin。

这个怎么运作

它运行一条show tables语句并将其存储在准备好的语句中。然后optimize table在选定集中运行一个。

您可以通过在var中设置其他值来控制要优化的表@tables_like(例如:)set @tables_like = '%test%';


4
我的共享托管环境没有'mysqlchk'可用,因此我可以直接从'mysql'终端会话运行它。谢谢!
funwhilelost 2014年

别客气。我使用此代码来优化50个数据库,并花费最少的时间。如果您认为我可以以任何方式改进代码,请继续提出您的建议。我将很乐意改进这段宝贵的代码。
Ismael Miguel

bd使用@b进行准备,错误代码:1064。检查与您的MySQL服务器版本相对应的手册以获取正确的语法,以在第1行的'NULL'附近使用
Paul Gregoire 2014年

@IsmaelMiguel这是MySQL,您的答案使用TSQL语法,不适用于MySQL。
Phrancis

2
@LorenzoBelfanti感谢您确认。令我高兴的是,即使经过2年,此代码也至少对10个人有用。对我来说,这是巨大的胜利!再次感谢您!
Ismael Miguel

20

以下示例php脚本可以帮助您优化数据库中的所有表

<?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
在具有200个表的数据库中,您将运行200个单独的查询,一次优化1个表。您应该将表名称内嵌到一个字符串中,因此仅需要一个优化表查询。
Dean Marshall

8
我想知道单独的查询方法是否有时更好。MySQL说在OPTIMIZE TABLE运行时表被锁定。然后,一次优化每个锁以让服务器在最短时间内获取锁似乎更为明智。显然,这是用于一直被访问的服务器。如果没有,那么我认为单个查询是最好的方法。
glarrain 2012年

如果内爆并进行1次查询,脚本将是什么样?谢谢。
H. Ferrence,2012年

8
@Dean单独的查询方法通常更好地为实时应用程序腾出空间。实际上,我通常为此目的添加一个延迟(仅750ms左右)。
zanlok

15

执行所有必要的过程,以使用简单的shell脚本修复所有数据库中的所有表:

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

11

对于所有数据库:

mysqlcheck -Aos -uuser -p 

对于一个数据库优化:

mysqlcheck -os -uroot -p dbtest3

至少对我来说,在Linux下,该命令mysqlcheck -Aos不需要用户+密码。
Zuul

7

从phpMyAdmin和其他来源,您可以使用:

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

然后,您可以将结果复制并粘贴到新查询中,或者从您自己的源中执行它。如果看不到整个语句: phpmyadmin中查看整个语句的方法


那是一个很好的答案,但是我的phpmyadmin并没有显示整个命令,而是仅显示第一个命令。
MonneratRJ

6

如果要分析,修复和优化MySQL服务器中所有数据库中的所有表,则可以从命令行一次性完成。您将需要root来执行此操作。

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

运行该命令后,将提示您输入MySQL根密码。之后,它将开始,并且您将看到正在发生的结果。

输出示例:

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

如果您不知道root密码,并且正在使用WHM,则可以通过以下步骤在WHM中进行更改: 主页> SQL Services> MySQL Root Password


5

从命令行:

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

然后输入密码


4

您可以使用mysql客户端优化/检查和修复数据库的所有表。

首先,您应该获取所有表列表,并用“,”分隔:

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

现在,当您拥有所有要优化的表列表时:

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

3

MySQL Administrator(MySQL的GUI工具的一部分),可以为你做的数据库级别。

只需选择您的架构,然后按 Maintenance右下角按钮即可。

由于GUI工具已达到寿命终止状态,因此很难在mysql页面上找到它们。通过Google找到了它们: http //dev.mysql.com/downloads/gui-tools/5.0.html

我不知道新的MySQL Workbench是否也可以做到这一点。

您也可以使用mysqlcheck命令行工具来执行此操作。


2

如果直接访问数据库,则可以编写以下查询:

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

1

此bash脚本将接受root密码作为选项,并一步一步对其进行优化,并显示状态输出:

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

入门bash脚本,用于针对数据库列出并运行工具...

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

我的2美分:从碎片最多的表格开始

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.