如何定位到查询慢的sql语句
- 通过慢查询日志定位那些执行效率较低的SQL语句,用–log-slow-queries[=file_name]选项启动时,mysqld写一个包含所有执行时间超过long_query_time秒的SQL语句的日志文件。
- 慢查询日志在查询结束以后才记录,所以在应用反映执行效率出现问题的时候查询慢查询日志文件并不能定位问题,可以使用show processlist命令查看当前MySQL在进行的线程,包括线程的状态,是否锁表等等,可以实时地查看SQL的执行情况,同时对一些锁表操作进行优化。
用EXPLAIN分析是什么原因造成sql的查询很慢
其中各个字段的含义如下表所示
字段 | 含义 |
---|---|
id | select查询的序列号,是一组数字,表示的是查询中执行select子句或者是操作表的顺序。 |
select_type | SELELCT的类型表示 SELECT 的类型,常见的取值有 SIMPLE(简单表,即不使用表连接或者子查询)、PRIMARY(主查询,即外层的查询)、UNION(UNION 中的第二个或者后面的查询语句)、SUBQUERY(子查询中的第一个 SELECT)等 |
table | 输出结果集的表 |
type | 表示表的连接类型,常见的连接类型性能由好到坏为 ALL->index->range->ref->eq_ref->const,system->NULL |
possible_keys | 表示查询时,可能使用的索引 |
key | 表示实际使用的索引 |
key_len | 索引字段的长度 |
rows | 扫描行的数量 |
extra | 执行情况的说明和描述 |
type字段的解释
-
type=NULL,全表扫描
-
type=index,索引全扫描,MySQL遍历整个索引来查询匹配的行
-
type=range,索引范围扫描,常见于<、<=、>、>=、between等操作符
-
type=ref,使用非唯一索引扫描或唯一索引的前缀扫描,返回匹配某个单独值得记录行
-
type=eq_ref,类似于ref,但是使用的是唯一索引,对于每一个索引键值,表中只有一条记录匹配,多表连接中使用primary key 或者 unique index作为关联条件。
-
type = const/system,单表中最多一个匹配行,查询起来非常迅速,所以这个匹配行中的其他列的值可以被优化器在当前查询中当做常量来处理,例如,根据主键primary key 或者唯一索引unique index进行的查询
-
type=NULL,MySQL不用访问表或者索引,直接就能得到结果
用索引进行优化
根据上述步骤我们可以确定问题的原因,例如我们确定了对客户表customer的全表扫描导致效率不理想,那么我们可以对客户表的customer的email字段创建索引
使用索引之前查询效果如下
添加索引后
如何使用索引(什么情况下能让索引生效)
在知道我们应该用索引来优化查询之后,我们更进一步地应该了解,什么情况下索引能够生效,索引使用于什么场景之下
-
匹配全值
对索引中所有的列都指定值,例如我们有关于三列的索引出租日期rental_data(idx_rental_date),库存编号inventory_id(idx_fk_inventory),客户编号customer(idx_fk_customer_id)
-
匹配值的范围查询
对索引的列值可以进行范围查找
所谓的回表查询值得是:第一次使用idx_fk_customer_id索引查到了主键值,然后再根据主键值来找到对应的数据 -
匹配最左前缀
对于联合索引(col1,col2,col3)而言,能够被col1、(col1 + col2)、(col1 + col2 + col3)查到,但是不能够被col2、(col2 + col3)查询
关于mysql最左匹配的理解:mysql最左匹配的理解,mysql最左匹配原则 -
仅仅对索引进行查询,当查询的列都在索引的字段中,查询效率高
关于索引覆盖推荐这篇文章:什么是索引覆盖,强力推荐 -
匹配列前缀
同理最最左匹配规则的原理 -
索引匹配部分精确而其他部分进行范围匹配
-
如果列名是索引,那么使用column_name is null 就会使用索引
参考文章
mysql最左匹配的理解
mysql最左匹配原则
什么是索引覆盖,强力推荐
《深入浅出MySQL》