MySQL 分析表、检查表和优化表
对于大多数开发者来说,他们更倾向于解决简单 SQL的优化,而复杂 SQL 的优化交给了公司的 DBA 来做。
下面就从普通程序员的角度和你聊几个简单的优化方式。
MySQL 分析表
分析表用于分析和存储表的关键字分布,分析的结果可以使得系统得到准确的统计信息,使得 SQL 生成正确的执行计划。如果用于感觉实际执行计划与预期不符,可以执行分析表来解决问题,分析表语法如下
analyze table cxuan005;
分析结果涉及到的字段属性如下
Table:表示表的名称;
Op:表示执行的操作,analyze 表示进行分析操作,check 表示进行检查查找,optimize 表示进行优化操作;
Msg_type:表示信息类型,其显示的值通常是状态、警告、错误和信息这四者之一;
Msg_text:显示信息。
对表的定期分析可以改善性能,应该成为日常工作的一部分。因为通过更新表的索引信息对表进行分析,可改善数据库性能。
MySQL 检查表
数据库经常可能遇到错误,比如数据写入磁盘时发生错误,或是索引没有同步更新,或是数据库未关闭 MySQL 就停止了。遇到这些情况,数据就可能发生错误:Incorrect key file for table: ' '. Try to repair it. 此时,我们可以使用 Check Table 语句来检查表及其对应的索引。
check table cxuan005;
检查表的主要目的就是检查一个或者多个表是否有错误。Check Table 对 MyISAM 和 InnoDB 表有作用。Check Table 也可以检查视图的错误。
MySQL 优化表
MySQL 优化表适用于删除了大量的表数据,或者对包含 VARCHAR、BLOB 或则 TEXT 命令进行大量修改的情况。MySQL 优化表可以将大量的空间碎片进行合并,消除由于删除或者更新造成的空间浪费情况。它的命令如下
optimize table cxuan005;
我的存储引擎是 InnoDB 引擎,但是从图可以知道,InnoDB 不支持使用 optimize 优化,建议使用 recreate + analyze 进行优化。optimize 命令只对 MyISAM 、BDB 表起作用。
常用 SQL 优化
前面我们介绍了使用索引来优化 MySQL ,那么对于 SQL 的各种语法,句法来说,应该怎样优化呢?下面,我会从 SQL 命令的角度来聊一波 SQL 优化。
导入的优化
对于 MyISAM 类型的表,可以通过下面这种方式导入大量的数据
ALTER TABLE tblname DISABLE KEYS; loading the data ALTER TABLE tblname ENABLE KEYS;
这两个命令用来打开或者关闭 MyISAM 表非唯一索引的更新。在导入大量的数据到一个非空的 MyISAM 表时,通过设置这两个命令,可以提高导入的效率。对于导入大量数据到一个空的 MyISAM 表,默认就是先导入数据然后才创建索引,所以不用进行设置。
但是对于 InnoDB 搜索引擎的表来说,这样做不能提高导入效率,我们有以下几种方式可以提高导入的效率:
- 因为 InnoDB 类型的表是按照主键的顺序保存的,所以将导入的数据按照主键的顺序排列,可以有效的提高导入数据的效率。如果 InnoDB 表没有主键,那么系统会默认创建一个内部列作为主键,所以如果可以给表创建一个主键,将可以利用这个优势提高导入数据的效率。
- 在导入数据前执行 SET UNIQUE_CHECKS = 0,关闭唯一性校验,在导入结束后执行SETUNIQUE_CHECKS = 1,恢复唯一性校验,可以提高导入的效率。
- 如果应用使用自动提交的方式,建议在导入前执行 SET AUTOCOMMIT = 0,关闭自动提交,导入结束后再执行 SET AUTOCOMMIT = 1,打开自动提交,也可以提高导入的效率。
insert 的优化
当进行插入语句的时候,可以考虑采用下面这几种方式进行优化
- 如果向同一张表插入多条数据的话,最好一次性插入,这样可以减少数据库建立连接 -> 断开连接的时间,如下所示
insert into test values(1,2),(1,3),(1,4)
- 如果向不同的表插入多条数据,可以使用 insert delayed 语句提高执行效率。delayed 的含义是让 insert 语句马上执行,要么数据都会放在内存的队列中,并没有真正写入磁盘。
- 对于 MyISAM 表来说,可以增加 bulk_insert_buffer_size 的值提高插入效率。
- 最好将索引和数据文件在不同的磁盘上存放。
group by 的优化
在使用分组和排序的场景下,如果先进行 Group By 再进行 Order By 的话,可以指定 order by null 禁止排序,因为 order by null 可以避免 filesort
,filesort 往往很耗费时间。如下所示
explain select id,sum(moneys) from sales2 group by id order by null;
order by 的优化
在执行计划中,经常可以看到 Extra
列出现了 filesort,filesort 是一种文件排序,这种排序方式比较慢,我们认为是不好的排序,需要进行优化。
优化的方式是要使用索引。
我们在 cxuan005 上创建一个索引。
create index idx on cxuan005(id);
然后我们使用查询字段和排序相同的顺序进行查询。
explain select id from cxuan005 where id > '111' order by id;
可以看到,在这次查询中,使用的是 Using index
。这表明我们使用的是索引。
如果创建索引和 order by 的顺序不一致,将会使用 Using filesort。
explain select id from cxuan005 where id > '111' order by info;
MySQL 支持两种方式的排序,filesort 和 index,Using index 是指 MySQL 扫描索引本身完成排序。index 效率高,filesort 效率低。
order by 在满足下面这些情况下才会使用 index
- order by 语句使用索引最左前列。
- 使用 where 子句与 order by 子句条件列组合满足索引最左前列。