MySQL :: 如何为数据库中的所有表运行 ANALYZE TABLE

Sat*_*ave 5 mysql index-statistics mysql-5.7

我正在使用 MySQL 5.7

如何为数据库中的所有表运行 ANALYZE TABLE。如果将来将新表添加到数据库中,它应该可以工作。

这是为了刷新表索引的统计信息。

小智 8

你可以运行

mysqlcheck -a --all-databases
Run Code Online (Sandbox Code Playgroud)

  • 如果您希望针对特定数据库运行“mysqlcheck -a [database]”,则只需运行“mysqlcheck -a [database]”,它将针对默认给定的数据库中的所有表运行(参见https://dev.mysql.com/doc/refman/8.0/ zh/mysqlcheck.html) (2认同)

Bil*_*win 6

如果您正在使用 InnoDB 表(您应该如此):

SET @old_innodb_stats_on_metadata = @@global.innodb_stats_on_metadata;
SET GLOBAL innodb_stats_on_metadata='ON';
SHOW TABLE STATUS FROM db;
SET GLOBAL innodb_stats_on_metadata = @old_innodb_stats_on_metadata;
Run Code Online (Sandbox Code Playgroud)

对于 InnoDB,如果我上面显示的选项为 ON,则 ANALYZE TABLE 执行的操作也仅通过查看表状态来执行。也就是说,查看表状态或查询 INFORMATION_SCHEMA.TABLES 将触发与 ANALYZE TABLE 相同的表统计信息刷新。

该语句SHOW TABLE STATUS FROM db默认显示命名模式中的所有表,因此无需编写循环或其他答案所示的任何内容。

  • MySQL 文档还说:“此选项仅适用于优化器统计信息配置为非持久性时。当禁用 innodb_stats_persistent 或使用 STATS_PERSISTENT=0 创建或更改单个表时,优化器统计信息不会持久保存到磁盘。” (2认同)

小智 1

我想要一种方法来获取数据库中每个表中的确切行数,并发现ANALYZE TABLE table_name需要确保该值正确。我无法将变量传递table_nameANALYZE TABLE,所以这是我能做的最好的事情。

总之:

  • 创建一个script_to_analyse_all_tables()循环遍历每个表名称的存储过程,为每个表生成查询ANALYZE TABLE table_name
  • 调用这个存储过程
  • 之后删除此存储过程(如果您不想保留它)

然后,手动:

  • 复制输出
  • 在 MySQL Workbench 中粘贴并运行输出。

只需db_name在运行之前更新数据库的名称即可。

DROP PROCEDURE IF EXISTS `script_to_analyse_all_tables`;
DELIMITER $$
CREATE PROCEDURE script_to_analyse_all_tables()
BEGIN
    -- declare variables
    DECLARE finished INTEGER DEFAULT 0;
    DECLARE this_table_name VARCHAR(256); 
    DECLARE full_statement VARCHAR(10000); 
    -- declare cursor for table names
    DECLARE cursor_table_name CURSOR FOR 
        SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '[db_name]';
    -- declare NOT FOUND handler
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
    
    -- open the cursor
    OPEN cursor_table_name;
    
    myLoop: LOOP
        FETCH cursor_table_name INTO this_table_name;
        IF finished = 1 THEN 
            LEAVE myLoop;
        END IF;
        SET full_statement = concat( IFNULL(full_statement,''), "ANALYZE TABLE ", this_table_name, ";");
    END LOOP myLoop;
    -- close the cursor
    CLOSE cursor_table_name;
    -- view results:
    SELECT full_statement as "run the following statement:";
    
END $$
DELIMITER ;

CALL script_to_analyse_all_tables;

DROP PROCEDURE IF EXISTS `script_to_analyse_all_tables`;
Run Code Online (Sandbox Code Playgroud)

然后使用以下命令检查结果:

SELECT table_name, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '[db_name]';