mysql语句性能分析案例
写法不一样而功能完全相同的两条 SQL 的在性能方面的差异。
示例一
需求:取出某个 group(假设 id 为 100)下的用户编号(id),用户昵称(nick_name)、用户性别
( sexuality ) 、 用 户 签 名 ( sign ) 和 用 户 生 日 ( birthday ) , 并 按 照 加 入 组 的 时 间
(user_group.gmt_create)来进行倒序排列,取出前 20 个。
解决方案一、
SELECT id,nick_name
FROM user,user_group
WHERE user_group.group_id = 1
and user_group.user_id = user.id
limit 100,20;
解决方案二、
SELECT user.id,user.nick_name
FROM (
SELECT user_id
FROM user_group
WHERE user_group.group_id = 1
ORDER BY gmt_create desc
limit 100,20) t,user
WHERE t.user_id = user.id;
我们先来看看执行计划:
sky@localhost : example 10:32:13> explain
-> SELECT id,nick_name
-> FROM user,user_group
-> WHERE user_group.group_id = 1
-> and user_group.user_id = user.id
-> ORDER BY user_group.gmt_create desc
-> limit 100,20\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: user_group
type: ref
possible_keys: user_group_uid_gid_ind,user_group_gid_ind
key: user_group_gid_ind
key_len: 4
ref: const
rows: 31156
Extra: Using where; Using filesort
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: user
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: example.user_group.user_id
rows: 1
Extra:
sky@localhost : example 10:32:20> explain
-> SELECT user.id,user.nick_name
-> FROM (
-> SELECT user_id
-> FROM user_group
-> WHERE user_group.group_id = 1
-> ORDER BY gmt_create desc
-> limit 100,20) t,user
-> WHERE t.user_id = user.id\G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 20
Extra:
*************************** 2. row ***************************
id: 1
select_type: PRIMARY
table: user
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: t.user_id
rows: 1
Extra:
*************************** 3. row ***************************
id: 2
select_type: DERIVED
table: user_group
type: ref
possible_keys: user_group_gid_ind
key: user_group_gid_ind
key_len: 4
ref: const
rows: 31156
Extra: Using filesort
执行计划对比分析:
解决方案一中的执行计划显示 MySQL 在对两个参与 Join 的表都利用到了索引,user_group 表利用了
user_group_gid_ind 索 引 ( key: user_group_gid_ind ) , user 表 利 用 到 了 主 键 索 引 ( key:
PRIMARY),在参与 Join 前 MySQL 通过 Where 过滤后的结果集与 user 表进行 Join,最后通过排序取出
Join 后结果的“limit 100,20”条结果返回。
解决方案二的 SQL 语句利用到了子查询,所以执行计划会稍微复杂一些,首先可以看到两个表都和
解决方案 1 一样都利用到了索引(所使用的索引也完全一样),执行计划显示该子查询以 user_group 为
驱动,也就是先通过 user_group 进行过滤并马上进行这一论的结果集排序,也就取得了 SQL 中的
“limit 100,20”条结果,然后与 user 表进行 Join,得到相应的数据。这里可能有人会怀疑在自查询中
从 user_group 表所取得与 user 表参与 Join 的记录条数并不是 20 条,而是整个 group_id=1 的所有结果。
那么清大家看看该执行计划中的第一行,该行内容就充分说明了在外层查询中的所有的 20 条记录全部被
返回。
通过比较两个解决方案的执行计划,我们可以看到第一中解决方案中需要和 user 表参与 Join 的记录
数 MySQL 通过统计数据估算出来是 31156,也就是通过 user_group 表返回的所有满足 group_id=1 的记录
数(系统中的实际数据是 20000)。而第二种解决方案的执行计划中,user 表参与 Join 的数据就只有 20
条,两者相差很大,通过本节最初的分析,我们认为第二中解决方案应该明显优于第一种解决方案。
下面我们通过对比两个解决觉方案的 SQL 实际执行的 profile 详细信息,来验证我们上面的判断。由
于 SQL 语句执行所消耗的最大两部分资源就是 IO 和 CPU,所以这里为了节约篇幅,仅列出 BLOCK IO 和 CPU
两项 profile 信息(Query Profiler 的详细介绍将在后面章节中独立介绍):
先打开 profiling 功能,然后分别执行两个解决方案的 SQL 语句:
sky@localhost : example 10:46:43> set profiling = 1;
Query OK, 0 rows affected (0.00 sec)
sky@localhost : example 10:46:50> SELECT id,nick_name
-> FROM user,user_group
-> WHERE user_group.group_id = 1
-> and user_group.user_id = user.id
-> ORDER BY user_group.gmt_create desc
-> limit 100,20;
+--------+-----------+
| id | nick_name |
+--------+-----------+
| 990101 | 990101 |
| 990102 | 990102 |
| 990103 | 990103 |
| 990104 | 990104 |
| 990105 | 990105 |
| 990106 | 990106 |
| 990107 | 990107 |
| 990108 | 990108 |
| 990109 | 990109 |
| 990110 | 990110 |
| 990111 | 990111 |
| 990112 | 990112 |
| 990113 | 990113 |
| 990114 | 990114 |
| 990115 | 990115 |
| 990116 | 990116 |
| 990117 | 990117 |
| 990118 | 990118 |
| 990119 | 990119 |
| 990120 | 990120 |
+--------+-----------+
20 rows in set (1.02 sec)
sky@localhost : example 10:46:58> SELECT user.id,user.nick_name
-> FROM (
-> SELECT user_id
-> FROM user_group
-> WHERE user_group.group_id = 1
-> ORDER BY gmt_create desc
-> limit 100,20) t,user
-> WHERE t.user_id = user.id;
+--------+-----------+
| id | nick_name |
+--------+-----------+
| 990101 | 990101 |
| 990102 | 990102 |
| 990103 | 990103 |
| 990104 | 990104 |
| 990105 | 990105 |
| 990106 | 990106 |
| 990107 | 990107 |
| 990108 | 990108 |
| 990109 | 990109 |
| 990110 | 990110 |
| 990111 | 990111 |
| 990112 | 990112 |
| 990113 | 990113 |
| 990114 | 990114 |
| 990115 | 990115 |
| 990116 | 990116 |
| 990117 | 990117 |
| 990118 | 990118 |
| 990119 | 990119 |
| 990120 | 990120 |
+--------+-----------+
20 rows in set (0.96 sec)
查看系统中的 profile 信息,刚刚执行的两个 SQL 语句的执行 profile 信息已经记录下来了:
sky@localhost : example 10:47:07> show profiles\G
*************************** 1. row ***************************
Query_ID: 1
Duration: 1.02367600
Query: SELECT id,nick_name
FROM user,user_group
WHERE user_group.group_id = 1
and user_group.user_id = user.id
ORDER BY user_group.gmt_create desc
limit 100,20
*************************** 2. row ***************************
Query_ID: 2
Duration: 0.96327800
Query: SELECT user.id,user.nick_name
FROM (
SELECT user_id
FROM user_group
WHERE user_group.group_id = 1
ORDER BY gmt_create desc
limit 100,20) t,user
WHERE t.user_id = user.id
2 rows in set (0.00 sec)
sky@localhost : example 10:47:34> SHOW profile CPU,BLOCK IO io FOR query 1;
16 rows in set (0.00 sec)
sky@localhost : example 10:47:40> SHOW profile CPU,BLOCK IO io FOR query 2;
我们先看看两条 SQL 执行中的 IO 消耗,两者区别就在于“Sorting result”,我们回
顾一下前面执行计划的对比,两个解决方案的排序过滤数据的时机不一样,排序后需要取
得的数据量一个是 20000,一个是 20,正好和这里的 profile 信息吻合,第一种解决方案的
“Sorting result”的 IO 值是第二种解决方案的将近 500 倍。
然后再来看看 CPU 消耗,所有消耗中,消耗最大的也是“Sorting result”这一项,第
一个消耗多出的缘由和上面 IO 消耗差异是一样的。
结论:
通过上面两条功能完全相同的 SQL 语句的执行计划分析,以及通过实际执行后的
profile 数据的验证,都证明了第二种解决方案优于第一种解决方案。
mysql语句性能分析案例的更多相关文章
- mysql语句性能分析
1.开启慢查询 slow_query_log = 1 //开启 slow_query_log_file = mysql_slow_query.log //日志文件位置 long_query_time ...
- DB-MySQL:MySQL 语句性能优化
ylbtech-DB-MySQL:MySQL 语句性能优化 1.返回顶部 1. MySQL概述1.数据库设计 3范式2.数据库分表分库---会员系统() 水平分割(分页如何查询)MyChar .垂直3 ...
- MySQL优化 - 性能分析与查询优化(转)
出处: MySQL优化 - 性能分析与查询优化 优化应贯穿整个产品开发周期中,比如编写复杂SQL时查看执行计划,安装MySQL服务器时尽量合理配置(见过太多完全使用默认配置安装的情况),根据应用负载 ...
- SQL语句性能分析
SQL语句性能分析 explain执行计划 用法: explain select 语句 命令: show database; use mysql explain select * from user; ...
- MySQL 索引性能分析概要
上一篇文章 MySQL 索引设计概要 介绍了影响索引设计的几大因素,包括过滤因子.索引片的宽窄与大小以及匹配列和过滤列.在文章的后半部分介绍了 数据库索引设计与优化 一书中,理想的三星索引的设计流程和 ...
- MySQL索引性能分析
为什么要做性能分析 你有没有这样的情况. 面对一个你没怎么写过的.复杂的业务,你构思了很久,终于开始敲下了第一段代码. 写的过程迷迷糊糊,有的时候还能把自己搞晕了. 但你还是终于把它写完了. 但是点击 ...
- mysql Explain 性能分析关键字
EXPLAIN 输出格式select_typetabletypepossible_keyskeykey_lenrowsExtra MySQL 提供了一个 EXPLAIN 命令, 它可以对 SELECT ...
- MySQL优化 - 性能分析与查询优化
优化应贯穿整个产品开发周期中,比如编写复杂SQL时查看执行计划,安装MySQL服务器时尽量合理配置(见过太多完全使用默认配置安装的情况),根据应用负载选择合理的硬件配置等. 1.性能分析 性能分析包含 ...
- [转] Android 性能分析案例
Android 系统的一个工程师(Romain Guy)针对Falcon Pro 应用,撰写了一个Android性能分析的文章.该文章介绍了如何分析一个应用哪里出现了性能瓶颈,导致该应用使用起来不流 ...
随机推荐
- Java SE 8 并发增强
1.原子值 java5开始,提供了一些原子操作的类,如AtomicInteger.AtomicLong等 这些类提供了诸如incrementAndGet这样的原子操作方法. 单数如果想进行复杂操作,则 ...
- 有术:DIY代理服务器
FQ有术:DIY代理服务器 公司HTTP代理穿透+手機ShadowSocks+SSH翻牆 利用SSH代理爬墙 http://bestvpnchina.net/
- PHP上传原理及操作实现
关于PHP上传文件的函数类库,网上有许多封装很完善,大家直接拿来用就可以. 本文章只是说下关于上传原理和简单的上传操作,老鸟就无视了哈^_^~ 还有一些安全性判断比如:服务端限制能接收图片类型的文件, ...
- 内存管理 初始化(八) 至kswapd_init
至此,内存初始化部分已看完,遗留问题: 1.对于unicore或者mips的页表建立都很清楚,但是对于ARM我不清楚: 初始化部分涉及的页表映射建立,我都以unicore架构为准,ARM的页表映射从原 ...
- kafka学习之-server.properties详细说明
http://blog.csdn.net/lizhitao/article/details/25667831 -- 参考文章 http://kafka.apache.org/documentatio ...
- Window 10 :我的性能优化:那效果,杠杠的!
微软的 windows 10,不错! 当全新安装后,性能总觉得别别扭扭,不那么干净利落. 下面就是我的个人优化措施,期间有很多技术性的操作,如果你没有动手能力,或者是技术小白,可以不用再看了! (1) ...
- consul在windows下的安装
consul的下载 https://www.consul.io/downloads.html 选择对应的系统版本 修改环境变量path 启动命令窗口 执行命令 consul agent -dev 打开 ...
- hdfs 机架感知
一.背景 分布式的集群通常包含非常多的机器,由于受到机架槽位和交换机网口的限制,通常大型的分布式集群都会跨好几个机架,由多个机架上的机器共同组成一个分布式集群.机架内的机器之间的网络速度通常都会高 ...
- 数据库事务MTDC出错解决办法
Communication with the underlying transaction manager has failed 与基础事务管理器的通信失败 排除步驟: 1.檢查MS DTC 設置.[ ...
- SpringBoot------thymeleaf的使用
1.pom.xml添加相应依赖 <dependency> <groupId>org.springframework.boot</groupId> <artif ...