今天想的利用explain与progiling分析下语句然后进行优化。本文重点是如何通过explain与profiling分析SQL执行过程与性能。进而明白索引的重要性。

表的关系如下所示:

原始的查询SQL:(根据用户的ID查看用户的权限)

SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role
WHERE userid = 'b33b938faada40aeac2b5ca228336473'))

-----------------------------------不加索引的分析以及测试-----------------------------------------

1.分析

首先将三个表的索引全部去掉  (只剩下主键索引)

查看三个表的索引:

mysql> SHOW INDEX FROM  permission\G
*************************** 1. row ***************************
Table: permission
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: permissionID
Collation: A
Cardinality: 50
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec) mysql> SHOW INDEX FROM rolepermission\G
*************************** 1. row ***************************
Table: rolepermission
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: rolePermissionId
Collation: A
Cardinality: 66
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec) mysql> SHOW INDEX FROM user_role\G
*************************** 1. row ***************************
Table: user_role
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: userRoleID
Collation: A
Cardinality: 4
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec) mysql>

1.  explain 分析上面SQL的执行计划:

EXPLAIN
SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role
WHERE userid = 'b33b938faada40aeac2b5ca228336473'))

结果:

分析:

  ID越大越先执行,ID相同的按顺序从上向下执行。

  查询rolepermission和userrole都是全表扫描(type为All),且未用到任何索引,只有查询permission用到了主键索引。且看到后连个表的命中率也都比较低。

  关于更全的参数解释参考:https://www.cnblogs.com/qlqwjy/p/7767479.html

2.通过profiling分析语句:

0.可以在执行之前清空查询缓存

reset query cache;

1、 开启 profiling 参数

root@localhost : (none) 10:53:11> set profiling=1;
Query OK, 0 rows affected (0.00 sec)

通过执行 “set profiling”命令,可以开启关闭 Query Profiler 功能。

 2.执行query:

SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role
WHERE userid = 'b33b938faada40aeac2b5ca228336473'))

3、获取系统中保存的所有 Query 的 profile 概要信息

mysql> show profiles\G
*************************** 1. row **************************
Query_ID: 1
Duration: 0.01237475
Query: SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role 1 row in set, 1 warning (0.00 sec)

  分析  :     可以看到总共花了 12ms。

通过执行 “SHOW PROFILE” 命令获取当前系统中保存的多个 Query 的 profile 的概要信息。

4、针对单个 Query 获取详细的 profile 信息。

在获取到概要信息之后,我们就可以根据概要信息中的 Query_ID 来获取某个 Query 在执行过程中

详细的 profile 信息了,具体操作如下(1是上面的queryID)

mysql> show profile for query 1;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000819 |
| checking permissions | 0.000536 |
| checking permissions | 0.000519 |
| checking permissions | 0.000525 |
| Opening tables | 0.000700 |
| init | 0.000958 |
| System lock | 0.000989 |
| optimizing | 0.000557 |
| statistics | 0.000587 |
| preparing | 0.000519 |
| executing | 0.000492 |
| Sending data | 0.001388 |
| end | 0.000512 |
| query end | 0.000492 |
| removing tmp table | 0.000492 |
| query end | 0.000479 |
| closing tables | 0.000517 |
| freeing items | 0.000720 |
| cleaning up | 0.000577 |
+----------------------+----------+
19 rows in set, 1 warning (0.00 sec)

如果想查看cpu,io等信息更具体的信息可以:

mysql> show profile cpu, block io for query 1;
+----------------------+----------+----------+------------+--------------+-----
---------+
| Status | Duration | CPU_user | CPU_system | Block_ops_in | Bloc
_ops_out |
+----------------------+----------+----------+------------+--------------+-----
---------+
| starting | 0.000819 | 0.000000 | 0.000000 | NULL |
NULL |
| checking permissions | 0.000536 | 0.000000 | 0.000000 | NULL |
NULL |
| checking permissions | 0.000519 | 0.000000 | 0.000000 | NULL |
NULL |
| checking permissions | 0.000525 | 0.000000 | 0.000000 | NULL |
NULL |
| Opening tables | 0.000700 | 0.000000 | 0.000000 | NULL |
NULL |
| init | 0.000958 | 0.000000 | 0.000000 | NULL |
NULL |
| System lock | 0.000989 | 0.000000 | 0.000000 | NULL |
NULL |
| optimizing | 0.000557 | 0.000000 | 0.000000 | NULL |
NULL |
| statistics | 0.000587 | 0.000000 | 0.000000 | NULL |
NULL |
| preparing | 0.000519 | 0.000000 | 0.000000 | NULL |
NULL |
| executing | 0.000492 | 0.000000 | 0.000000 | NULL |
NULL |
| Sending data | 0.001388 | 0.000000 | 0.000000 | NULL |
NULL |
| end | 0.000512 | 0.000000 | 0.000000 | NULL |
NULL |
| query end | 0.000492 | 0.000000 | 0.000000 | NULL |
NULL |
| removing tmp table | 0.000492 | 0.000000 | 0.015625 | NULL |
NULL |
| query end | 0.000479 | 0.000000 | 0.000000 | NULL |
NULL |
| closing tables | 0.000517 | 0.000000 | 0.000000 | NULL |
NULL |
| freeing items | 0.000720 | 0.000000 | 0.000000 | NULL |
NULL |
| cleaning up | 0.000577 | 0.000000 | 0.000000 | NULL |
NULL |
+----------------------+----------+----------+------------+--------------+-----
---------+

2.测试修改SQL

将上述子查询SQL改为内连接查询:

SELECT *
FROM permission
INNER JOIN rolepermission
ON permission.permissionID = rolepermission.permissionId
INNER JOIN user_role
ON rolepermission.roleId = user_role.roleID
WHERE user_role.userID = 'b33b938faada40aeac2b5ca228336473'

1.explain分析:

分析:

EXPLAIN
SELECT *
FROM permission
INNER JOIN rolepermission
ON permission.permissionID = rolepermission.permissionId
INNER JOIN user_role
ON rolepermission.roleId = user_role.roleID
WHERE user_role.userID = 'b33b938faada40aeac2b5ca228336473'

结果:

分析:上面的子查询为四次查询,变为内连接查询为3此,且前两个未加索引,最后用到了主键索引。

2.通过profilies查看查询效率:

mysql> show profiles\G
*************************** 1. row ***************************
Query_ID: 1
Duration: 0.02015850
Query: SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role *************************** 2. row ***************************
Query_ID: 2
Duration: 0.01072575
Query: EXPLAIN
SELECT *
FROM permission
INNER JOIN rolepermission
ON permission.permissionID = rolepermission.permissionId
INNER JOIN user_role
ON rolepermission.roleId = user_role.roleID
WHERE user_role.userID = 'b33b938faada40aeac2b5ca228336473'
2 rows in set, 1 warning (0.00 sec)

发现变为内连接查询所花费的时间变为原来的一班,原来20ms,现在10ms。

多查询几次,查看效率:

mysql> show profiles\G
*************************** 1. row ***************************
Query_ID: 1
Duration: 0.01448950
Query: SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role *************************** 2. row ***************************
Query_ID: 2
Duration: 0.01417150
Query: SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role *************************** 3. row ***************************
Query_ID: 3
Duration: 0.01466100
Query: SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role *************************** 4. row ***************************
Query_ID: 4
Duration: 0.01308100
Query: SELECT *
FROM permission
inner join rolepermission
on permission.permissionID = rolepermission.permissionId
INNER join user_role
on rolepermission.roleId = user_role.roleID
where user_role.userID = 'a9e65788297e4a8cb68a369522ee5af7'
*************************** 5. row ***************************
Query_ID: 5
Duration: 0.01334675
Query: SELECT *
FROM permission
inner join rolepermission
on permission.permissionID = rolepermission.permissionId
INNER join user_role
on rolepermission.roleId = user_role.roleID
where user_role.userID = 'a9e65788297e4a8cb68a369522ee5af7'
*************************** 6. row ***************************
Query_ID: 6
Duration: 0.01289250
Query: SELECT *
FROM permission
inner join rolepermission
on permission.permissionID = rolepermission.permissionId
INNER join user_role
on rolepermission.roleId = user_role.roleID
where user_role.userID = 'a9e65788297e4a8cb68a369522ee5af7'
6 rows in set, 1 warning (0.00 sec)

  前三条是子查询,后3条是内连接,发现内连接稍微快于子查询。

-----------------------------------加索引的分析以及测试-----------------------------------------

 0.在上面的表上加上索引

mysql> alter table user_role add index roleIdIndex(roleId);  #添加索引
Query OK, 0 rows affected (0.59 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table user_role add index userIdIndex(userId);
Query OK, 0 rows affected (0.53 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table rolepermission add index per_roleIdIndex(roleId);
Query OK, 0 rows affected (0.49 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table rolepermission add index per_perssionIdIndex(permissionId);
Query OK, 0 rows affected (0.38 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> show index from user_role\G  #查看索引
*************************** 1. row ***************************
Table: user_role
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: userRoleID
Collation: A
Cardinality: 4
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 2. row ***************************
Table: user_role
Non_unique: 1
Key_name: roleIdIndex
Seq_in_index: 1
Column_name: roleID
Collation: A
Cardinality: 3
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 3. row ***************************
Table: user_role
Non_unique: 1
Key_name: userIdIndex
Seq_in_index: 1
Column_name: userID
Collation: A
Cardinality: 3
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
3 rows in set (0.01 sec) mysql> show index from rolepermission\G  #查看索引
*************************** 1. row ***************************
Table: rolepermission
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: rolePermissionId
Collation: A
Cardinality: 66
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 2. row ***************************
Table: rolepermission
Non_unique: 1
Key_name: per_roleIdIndex
Seq_in_index: 1
Column_name: roleId
Collation: A
Cardinality: 4
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
*************************** 3. row ***************************
Table: rolepermission
Non_unique: 1
Key_name: per_perssionIdIndex
Seq_in_index: 1
Column_name: permissionId
Collation: A
Cardinality: 52
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
3 rows in set (0.01 sec)

1.针对子查询进行分析

1.explain分析:

EXPLAIN
SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role
WHERE userid = 'a9e65788297e4a8cb68a369522ee5af7'))

结果:

发现加上索引之后查询效果明显提升,三个表到用到索引,且命中率为100%。

2.profile分析:

mysql> show profiles\G*************************** 2. row ***************************
Query_ID: 2
Duration: 0.01505400
Query: SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role *************************** 3. row ***************************
Query_ID: 3
Duration: 0.01624350
Query: SELECT *
FROM permission
WHERE permissionid IN(SELECT
permissionid
FROM rolepermission
WHERE roleid IN(SELECT
roleid
FROM user_role 3 rows in set, 1 warning (0.00 sec) mysql>

数据量小没有多大影响。

2.针对显示内连接进行分析

1.explain分析

EXPLAIN
SELECT *
FROM permission
INNER JOIN rolepermission
ON permission.permissionID = rolepermission.permissionId
INNER JOIN user_role
ON rolepermission.roleId = user_role.roleID
WHERE user_role.userID = 'a9e65788297e4a8cb68a369522ee5af7'

结果:

2.show profile分析

*************************** 4. row ***************************
Query_ID: 4
Duration: 0.01447100
Query: SELECT *
FROM permission
INNER JOIN rolepermission
ON permission.permissionID = rolepermission.permissionId
INNER JOIN user_role
ON rolepermission.roleId = user_role.roleID
WHERE user_role.userID = 'a9e65788297e4a8cb68a369522ee5af7'
*************************** 5. row ***************************
Query_ID: 5
Duration: 0.01502600
Query: SELECT *
FROM permission
INNER JOIN rolepermission
ON permission.permissionID = rolepermission.permissionId
INNER JOIN user_role
ON rolepermission.roleId = user_role.roleID
WHERE user_role.userID = 'a9e65788297e4a8cb68a369522ee5af7'
*************************** 6. row ***************************
Query_ID: 6
Duration: 0.01471300
Query: SELECT *
FROM permission
INNER JOIN rolepermission
ON permission.permissionID = rolepermission.permissionId
INNER JOIN user_role
ON rolepermission.roleId = user_role.roleID
WHERE user_role.userID = 'a9e65788297e4a8cb68a369522ee5af7'
6 rows in set, 1 warning (0.00 sec)

子查询优化--explain与profiling分析语句的更多相关文章

  1. explain和profiling分析查询SQL时间

    mysql可以通过profiling命令查看到执行查询SQL消耗的时间. 默认情况下,mysql是关闭profiling的,命令: select @@profiling; +------------- ...

  2. mysql优化----explain的列分析

    sql语句优化: : sql语句的时间花在哪儿? 答: 等待时间 , 执行时间. 等待时间:看是不是被锁住了,那就不是语句层面了是服务端层面了,看连接数内存. 执行时间:到底取出多少行,一次性取出1万 ...

  3. 【MySQL】MySQL中针对大数据量常用技术_创建索引+缓存配置+分库分表+子查询优化(转载)

    原文地址:http://blog.csdn.net/zwan0518/article/details/11972853 目录(?)[-] 一查询优化 1创建索引 2缓存的配置 3slow_query_ ...

  4. 标量子查询优化(用group by 代替distinct)

    标量子查询优化 当使用另外一个SELECT 语句来产生结果中的一列的值的时候,这个查询必须只能返回一行一列的值.这种类型的子查询被称为标量子查询 在某些情况下可以进行优化以减少标量子查询的重复执行,但 ...

  5. MySQL慢查询优化 EXPLAIN详解

            我们平台过一段时间就会把生产数据库的慢查询导出来分析,要嘛修改写法,要嘛新增索引.以下是一些笔记.总结整理 慢查询排查         show status;  // 查询mysql ...

  6. postgresql子查询优化(提升子查询)

    问题背景 在开发项目过程中,客户要求使用gbase8s数据库(基于informix),简单的分页页面响应很慢.排查发现分页sql是先查询出数据在外面套一层后再取多少条,如果去掉嵌套的一层,直接获取则很 ...

  7. MySQL的EXPLAIN命令用于SQL语句的查询执行计划

    MySQL的EXPLAIN命令用于SQL语句的查询执行计划(QEP).这条命令的输出结果能够让我们了解MySQL 优化器是如何执行SQL 语句的.这条命令并没有提供任何调整建议,但它能够提供重要的信息 ...

  8. SQL优化之慢查询和explain以及性能分析

    性能优化的思路 首先需要使用慢查询功能,去获取所有查询时间比较长的SQL语句 使用explain去查看该sql的执行计划 使用show profile去查看该sql执行时的性能问题 MySQL性能优化 ...

  9. MySQL实验 子查询优化双参数limit

    MySQL实验 子查询优化双参数limit 没想到双参数limit还有优化的余地,为了亲眼见到,今天来亲自实验一下.   实验准备 使用MySQL官方的大数据库employees进行实验,导入该示例库 ...

随机推荐

  1. [C/C++] multimap查找一个key对应的多个value

    在multimap中,同一个键关联的元素必然相邻存放.基于这个事实,就可以将某个键对应的值一一输出. 1.使用find和count函数.count函数求出某个键出现的次数,find函数返回一个迭代器, ...

  2. delphi ERP框架

    之前做c/s架构,接了有家装饰的一个ERP项目,做了一个ERP框架,现在转后端开发了,这些东西还是蛮怀念的,就开源出来吧,有需要的同学可以参考. https://github.com/qianlnk/ ...

  3. 更新ffmpeg

    今天对公司线上的几台机器做了下ffmpeg的更新,没有什么技术含量,还是简单记录下,做个流水账~哈哈 软件包获取方式 官方网站:https://ffmpeg.org/download.htmlgith ...

  4. BZOJ5297 CQOI2018社交网络(矩阵树定理)

    板子题. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...

  5. P4596 [COCI2011-2012#5] RAZBIBRIGA

    题目描述 四个等长的单词可以放在一起构成一个正方形,两个单词水平放置,两个竖直放置.水平单词只能从左往右读,竖直的单词只能从上往下读.四个角共用一个字母. 图中是由单词HLAD,NIVA,HSIN,D ...

  6. Java pdf转String 并修正格式

    在尝试pdf转成String的时候,首先用python的pdfminer和pdfminer3k去尝试转换,然后资料看不太懂,就尝试用了java, 以下是java的pdfbox写的pdf转String函 ...

  7. iPhone X 的原深感模组

    物理与数字世界正走向融合,我们每天醒来的时间.睡眠时长.心率和步数等数据都会被分享.上传并转化为分析数据.无处不自的 AI.互联互通和软件平台将改变用户对现实的感知. 2018 年的 CES 展(国际 ...

  8. Spring点滴二:Spring Bean

    Spring Bean: 被称作bean的对象是构成应用程序的支柱,是由Spring Ioc容器管理.bean是一个被实例化,配置.组装并由Spring Ioc容器管理对象. 官网API:A Spri ...

  9. 设置Linux终端字体颜色

    系统启动后,环境变量加载的顺序为:/etc/profile → /etc/profile.d/*.sh → ~/.bash_profile → ~/.bashrc → /etc/bashrc 想要修改 ...

  10. Android Studio下“Error:Could not find com.android.tools.build:gradle:2.2.1”的解决方法

    ref from: Android Studio下“Error:Could not find com.android.tools.build:gradle:2.2.1”的解决方法http://blog ...