【问题标题】:MySQL OPTIMIZE all tables?MySQL 优化所有表?
【发布时间】:2011-07-25 09:13:04
【问题描述】:

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

【问题讨论】:

  • 请注意,这不一定会回收空间。如果您将 InnoDB 与单个文件(可能是当今最常见的设置)一起使用,而不是每个表单独的文件,那么最终您仍将使用相同数量的磁盘空间。事实上,我已经看到它实际上使用了更多的磁盘空间。对于大表,表也可能被锁定很长时间。
  • OPTIMIZE TABLE 对 MyISAM 很有用。现在该引擎即将消失,对 OPTIMIZE TABLE 的需求也将消失,尤其是需要定期优化所有表。
  • +1 for good info rick -- 但考虑到标准的现实世界数据库实践,如果旧的 MyISAM 表再存在十年,我不会感到惊讶

标签: mysql sql


【解决方案1】:

来自 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 没有显示整个命令,只显示第一个命令......我很伤心,哈哈。
【解决方案2】:

我的 1 美分,添加了 and TABLE_TYPE='BASE TABLE',因此我们可以跳过“VIEW”类型。

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') and TABLE_TYPE='BASE TABLE' order by data_free desc;"`
do
mysql -e "OPTIMIZE TABLE $table;"
done

【讨论】:

    【解决方案3】:

    我制作了这个“简单”的脚本:

    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%';)。

    【讨论】:

    • 我的共享主机环境没有 'mysqlchk' 可用,所以我可以直接从 'mysql' 终端会话运行它。谢谢!
    • 不客气。我使用这段代码优化了 50 个数据库,并尽可能减少了时间。如果您认为我可以以任何方式改进代码,请继续给我您的建议。我很乐意改进这段宝贵的代码。
    • Prepare bd from @b 错误代码:1064。您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“NULL”附近使用正确的语法
    • @IsmaelMiguel 这是 MySQL,您的答案使用 TSQL 语法,不适用于 MySQL。
    • @LorenzoBelfanti 感谢您的确认。我很高兴,即使在 2 年后,此代码至少对 10 人有用。这对我来说是一个巨大的胜利!再次感谢您!
    【解决方案4】:

    如果您是直接访问数据库,那么您可以编写以下查询:

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

    【讨论】:

      【解决方案5】:

      一个启动 bash 脚本,用于列出和运行针对 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
      

      【讨论】:

        【解决方案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 服务 > MySQL 根密码

        【讨论】:

          【解决方案7】:

          此 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
          

          【讨论】:

            【解决方案8】:

            我的 2cents:从碎片最高的表开始

            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
            

            【讨论】:

              【解决方案9】:

              MySQL Administrator(MySQL GUI 工具的一部分)可以在数据库级别为您做到这一点。

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

              由于 GUI 工具已达到生命周期结束状态,因此很难在 mysql 页面上找到它们。通过谷歌找到他们:http://dev.mysql.com/downloads/gui-tools/5.0.html

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

              您也可以使用mysqlcheck 命令行工具,它也应该能够做到这一点。

              【讨论】:

                【解决方案10】:

                对于所有数据库:

                mysqlcheck -Aos -uuser -p 
                

                对于一个数据库优化:

                mysqlcheck -os -uroot -p dbtest3
                

                【讨论】:

                • 至少对我来说,在Linux下,命令mysqlcheck -Aos不需要用户+密码。
                【解决方案11】:

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

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

                【讨论】:

                  【解决方案12】:

                  您可以使用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]
                  

                  【讨论】:

                    【解决方案13】:

                    从命令行:

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

                    然后输入密码

                    【讨论】:

                      【解决方案14】:

                      您可以在命令行中使用mysqlcheck 来执行此操作。

                      一个数据库:

                      mysqlcheck -o <db_schema_name>
                      

                      所有数据库:

                      mysqlcheck -o --all-databases
                      

                      【讨论】:

                      • 您是否建议将此命令安排为至少每月运行一次?
                      • 嗨@Gaia。不必要。在给定的时间表上优化所有表对每个人都没有好处。看看这篇文章并阅读 cmets 以获得比我在有限空间中提供的更深入的思考:xaprb.com/blog/2010/02/07/…
                      • 简单使用:mysqlcheck -u [username] -p[password] -o [database name]
                      • 请注意,在执行 OPTIMIZE 时,表已锁定,如果表包含大量数据,这可能需要很长时间。因此,在优化表期间,不能插入或删除新记录。一般来说,优化生产系统的所有表不能被认为是一项微不足道的操作。
                      • @No-Chip 您可以使用OPTIMIZE TABLE 命令在 MySQL 客户端中优化表:dev.mysql.com/doc/refman/5.5/en/optimize-table.html。例如,像这样优化一个表:OPTIMIZE TABLE &lt;your_schema&gt;.&lt;your_table&gt;;,像这样优化给定模式中的所有表: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;
                      【解决方案15】:

                      以下示例 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());
                      
                         }
                      }
                      
                      ?>
                      

                      【讨论】:

                      • 在具有 200 个表的数据库上,您将运行 200 个单独的查询,一次优化 1 个表。您应该将表名内爆到一个字符串中,因此只需要一个优化表查询。
                      • 我想知道单独的查询方法有时是否更好。 MySQL 说在 OPTIMIZE TABLE 运行时表被锁定。然后,一次优化每一个以让服务器在最短的时间内获取锁似乎更明智。显然,这是针对一直被访问的服务器的。如果不是,那么我认为单个查询是最好的方法。
                      • 如果你 imploded 并做成 1 个查询,脚本会是什么样子?谢谢。
                      • @Dean 单独的查询方法通常更好地为实时应用程序提供喘息的空间。事实上,我通常会为此添加一个延迟(仅 750 毫秒左右)。
                      猜你喜欢
                      • 2022-07-28
                      • 1970-01-01
                      • 2011-02-11
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-02-18
                      • 2021-10-27
                      相关资源
                      最近更新 更多