Muhammad Gelbana Asked: 2013-08-13 04:54:05 +0800 CST2013-08-13 04:54:05 +0800 CST 2013-08-13 04:54:05 +0800 CST 杀死 MyISAM 表上的 ANALYZE TABLE 查询是否安全? 772 我有一个巨大的 MyISAM 表,它阻塞了我的应用程序。我经常发现ANALYZE TABLE在该表上运行的查询。我想那是因为正在表上执行连接,或者至少正在使用索引,我不确定。 所以我想OPTIMIZE TABLE在表上运行一个查询来加快速度。但是目前有多个ANALAYZE TABLE查询锁定了表,那么杀死这些查询是否安全?我找不到关于 mysql 文档的足够信息。 谢谢。 mysql myisam 1 个回答 Voted Best Answer RolandoMySQLDBA 2013-08-13T08:04:45+08:002013-08-13T08:04:45+08:00 首先要知道的是什么ANALYZE TABLE。 对于 MyISAM 表mydb.mytable,ANALYZE TABLE遍历mytable.MYI文件中的所有索引,读取所有 BTREE 页面,计算统计信息,并将其存储在 information_schema 中,特别是STATISTICS. 当您运行以下之一时,您可以看到它: SHOW INDEXES FROM mydb.mytable; SELECT * FROM information_schema.statistics WHERE table_schema='mydb' AND table_name='mytable'; ANALYZE TABLE是一个只读操作并且确实发出一个表范围的读锁。 回答您的问题 是的,您可以杀死ANALYZE TABLE并短暂等待读取锁被释放。但是,有一个重大的惩罚。因为不会完全计算索引统计信息,所以 MySQL 查询优化器在生成针对该表的查询的 EXPLAIN 计划时会做出相当糟糕的猜测。 建议 建议#1:延迟ANALYZE TABLE 如果你想OPTIMIZE TABLE mydb.mytable不做ANALYZE TABLE操作就运行,请执行以下操作: ALTER TABLE mydb.mytable RENAME mydb.mytable_opt; ALTER TABLE mydb.mytable_opt ENGINE=MyISAM; ALTER TABLE mydb.mytable_opt RENAME mydb.mytable; 这将重命名表,执行碎片整理,然后将其重命名。 你也可以在一行中完成 ALTER TABLE mydb.mytable ENGINE=MyISAM; 如果您想ANALYZE TABLE稍后运行,请设置一个 cron 作业以在每个午夜或每周运行一次。如果您希望针对您的表的查询在优化后表现良好,那么您将不得不这样做。 建议 #2:将 MyISAM 表更改为 InnoDB 在 EXPLAIN 计划的生成过程中,InnoDB 将通过遍历 2-3 级非叶节点并从字面上近似(或真正猜测)所有列级别的基数来对表的索引页执行读取。您可以在运行时告诉 InnoDB 表正在发生这种情况,SHOW INDEXES FROM mydb.mytable;因为每次运行时基数都会发生变化。 鉴于此,您可以简单地运行 ALTER TABLE mydb.mytable ENGINE=InnoDB; 就是这样。即使您ANALYZE TABLE在 InnoDB 表上运行,统计信息也会变得相当陈旧。默认情况下,innodb_stats_on_metadata在 MySQL 5.6 中已禁用。如果您有 MySQL 5.5 及之前的版本,您可以通过执行以下操作禁用统计信息的更新: SET GLOBAL innodb_stats_on_metadata = 0; ANALYZE TABLE如果 InnoDB 表遇到较高的 INSERT、UPDATE 和 DELETE,您仍然必须硬着头皮在下游运行。否则,MySQL 查询优化器将对 EXPLAIN 计划做出错误的猜测。
首先要知道的是什么
ANALYZE TABLE
。对于 MyISAM 表
mydb.mytable
,ANALYZE TABLE
遍历mytable.MYI
文件中的所有索引,读取所有 BTREE 页面,计算统计信息,并将其存储在 information_schema 中,特别是STATISTICS
. 当您运行以下之一时,您可以看到它:SHOW INDEXES FROM mydb.mytable;
SELECT * FROM information_schema.statistics WHERE table_schema='mydb' AND table_name='mytable';
ANALYZE TABLE
是一个只读操作并且确实发出一个表范围的读锁。回答您的问题
是的,您可以杀死
ANALYZE TABLE
并短暂等待读取锁被释放。但是,有一个重大的惩罚。因为不会完全计算索引统计信息,所以 MySQL 查询优化器在生成针对该表的查询的 EXPLAIN 计划时会做出相当糟糕的猜测。建议
建议#1:延迟
ANALYZE TABLE
如果你想
OPTIMIZE TABLE mydb.mytable
不做ANALYZE TABLE
操作就运行,请执行以下操作:这将重命名表,执行碎片整理,然后将其重命名。
你也可以在一行中完成
如果您想
ANALYZE TABLE
稍后运行,请设置一个 cron 作业以在每个午夜或每周运行一次。如果您希望针对您的表的查询在优化后表现良好,那么您将不得不这样做。建议 #2:将 MyISAM 表更改为 InnoDB
在 EXPLAIN 计划的生成过程中,InnoDB 将通过遍历 2-3 级非叶节点并从字面上近似(或真正猜测)所有列级别的基数来对表的索引页执行读取。您可以在运行时告诉 InnoDB 表正在发生这种情况,
SHOW INDEXES FROM mydb.mytable;
因为每次运行时基数都会发生变化。鉴于此,您可以简单地运行
就是这样。即使您
ANALYZE TABLE
在 InnoDB 表上运行,统计信息也会变得相当陈旧。默认情况下,innodb_stats_on_metadata
在 MySQL 5.6 中已禁用。如果您有 MySQL 5.5 及之前的版本,您可以通过执行以下操作禁用统计信息的更新:ANALYZE TABLE
如果 InnoDB 表遇到较高的 INSERT、UPDATE 和 DELETE,您仍然必须硬着头皮在下游运行。否则,MySQL 查询优化器将对 EXPLAIN 计划做出错误的猜测。