加入收藏 | 设为首页 | 会员中心 | 我要投稿 西安站长网 (https://www.029zz.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

MySQL索引和SQL调优手册

发布时间:2019-09-26 09:40:26 所属栏目:建站 来源:吴德宝AllenWu
导读:副标题#e# MySQL索引 MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等。为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MySQL时主要打交道的索引。 MySQL

在日常工作中,我们有时会开慢查询去记录一些执行时间比较久的SQL语句,找出这些SQL语句并不意味着完事了,我们常常用到explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有没有使用上了索引,有没有做全表扫描,这都可以通过explain命令来查看。

所以我们深入了解MySQL的基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及当运行SQL语句时哪种策略预计会被优化器采用。

使用explain 只需要在原有select 基础上加上explain关键字就可以了,如下:

  1. mysql> explain select * from servers; 
  2. +----+-------------+---------+------+---------------+------+---------+------+------+-------+ 
  3. | id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows | Extra | 
  4. +----+-------------+---------+------+---------------+------+---------+------+------+-------+ 
  5. |  1 | SIMPLE      | servers | ALL  | NULL          | NULL | NULL    | NULL |    1 | NULL  | 
  6. +----+-------------+---------+------+---------------+------+---------+------+------+-------+ 
  7. 1 row in set (0.03 sec) 

简要解释下explain各个字段的含义

  • id : 表示SQL执行的顺序的标识,SQL从大到小的执行
  • select_type:表示查询中每个select子句的类型
  • table:显示这一行的数据是关于哪张表的,有时不是真实的表名字
  • type:表示MySQL在表中找到所需行的方式,又称“访问类型”。常用的类型有:ALL, index, range, ref, eq_ref, const, system, NULL(从左到右,性能从差到好)
  • possible_keys:指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用
  • Key:key列显示MySQL实际决定使用的键(索引),如果没有选择索引,键是NULL。
  • key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)
  • ref:表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
  • rows:表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数,理论上行数越少,查询性能越好
  • Extra:该列包含MySQL解决查询的详细信息

EXPLAIN的特性

  • EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
  • EXPLAIN不考虑各种Cache
  • EXPLAIN不能显示MySQL在执行查询时所作的优化工作
  • 部分统计信息是估算的,并非精确值
  • EXPALIN只能解释SELECT操作,其他操作要重写为SELECT后查看执行计划。
实战演练

表结构和查询语句

假如有如下表结构

  1. circlemessage_idx_0 | CREATE TABLE `circlemessage_idx_0` ( 
  2.   `circle_id` bigint(20) unsigned NOT NULL COMMENT '群组id', 
  3.   `from_id` bigint(20) unsigned NOT NULL COMMENT '发送用户id', 
  4.   `to_id` bigint(20) unsigned NOT NULL COMMENT '指定接收用户id', 
  5.   `msg_id` bigint(20) unsigned NOT NULL COMMENT '消息ID', 
  6.   `type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '消息类型', 
  7.   PRIMARY KEY (`msg_id`,`to_id`), 
  8.   KEY `idx_from_circle` (`from_id`,`circle_id`) 
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin 

通过执行计划explain分析如下查询语句

  1. mysql> explain select msg_id from circlemessage_idx_0 where  to_id = 113487 and circle_id=10019063  and msg_id>=6273803462253938690  and from_id != 113487 order by msg_id asc limit 30; 
  2. +----+-------------+---------------------+-------+-------------------------+---------+---------+------+--------+-------------+ 
  3. | id | select_type | table               | type  | possible_keys           | key     | key_len | ref  | rows   | Extra       | 
  4. +----+-------------+---------------------+-------+-------------------------+---------+---------+------+--------+-------------+ 
  5. |  1 | SIMPLE      | circlemessage_idx_0 | range | PRIMARY,idx_from_circle | PRIMARY | 16      | NULL | 349780 | Using where | 
  6. +----+-------------+---------------------+-------+-------------------------+---------+---------+------+--------+-------------+ 
  7. 1 row in set (0.00 sec) 
  1. mysql> explain select msg_id from circlemessage_idx_0 where  to_id = 113487 and circle_id=10019063   and from_id != 113487 order by msg_id asc limit 30; 
  2. +----+-------------+---------------------+-------+-----------------+---------+---------+------+------+-------------+ 
  3. | id | select_type | table               | type  | possible_keys   | key     | key_len | ref  | rows | Extra       | 
  4. +----+-------------+---------------------+-------+-----------------+---------+---------+------+------+-------------+ 
  5. |  1 | SIMPLE      | circlemessage_idx_0 | index | idx_from_circle | PRIMARY | 16      | NULL |   30 | Using where | 
  6. +----+-------------+---------------------+-------+-----------------+---------+---------+------+------+-------------+ 
  7. 1 row in set (0.00 sec) 

问题分析

通过上面两个执行计划可以发现当没有msg_id >= xxx这个查询条件的时候,检索的rows要少很多,并且两者查询的时候都用到了索引,而且用到的还只是主键索引。那说明索引应该是不合理的,没有发挥最大作用。

(编辑:西安站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读