SQL语句导致性能问题
前阵子,突然收到服务器的报警信息,于是上服务器找问题,我擦,top看到mysql占的%cpu高得把我吓尿了
从以上的信息看,相信大家已经可以定位到底是那个程序导致服务器CPU负载过高了,但我们要做的是,找出mysql进程下,是什么动作导致服务器出现性能问题
以下做个实验,相信大家看了后也能猜到当时是什么导致高负载的,废话不多说:
表结构如下:
mysql> desc test1;
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| role_id | int(11) | NO | | 0 | |
| referer | varchar(20) | NO | | | |
+---------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec) mysql> desc test2;
+--------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| role_id | int(11) | NO | MUL | 0 | |
| privilege_id | int(11) | NO | | 0 | |
+--------------+---------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
表的索引情况如下:
mysql> show index from test1;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| test1 | 0 | PRIMARY | 1 | id | A | 329 | NULL | NULL | | BTREE | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
1 row in set (0.00 sec) mysql> show index from test2;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| test2 | 0 | PRIMARY | 1 | id | A | 12476 | NULL | NULL | | BTREE | |
| test2 | 1 | role_id | 1 | role_id | A | 415 | NULL | NULL | | BTREE | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
2 rows in set (0.00 sec)
当时执行show full processlist后,发现有好几百个连接在执行同一条SQL语句,看见SQL也还好,不复杂,是子查询
mysql> select privilege_id from t2 where role_id in (select role_id from t1 where id=193);
看着以上的SQL语句,写没什么问题啊,但用explain分析一看,我擦
mysql> explain select privilege_id from test2 where role_id in (select role_id from test1 where id=192);
+----+--------------------+-------+-------+---------------+---------+---------+-------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+---------+---------+-------+-------+-------------+
| 1 | PRIMARY | test2 | ALL | NULL | NULL | NULL | NULL | 12476 | Using where |
| 2 | DEPENDENT SUBQUERY | test1 | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+----+--------------------+-------+-------+---------------+---------+---------+-------+-------+-------------+
2 rows in set (0.00 sec)
当时MySQL版本是:
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.1.66 |
+-----------+
1 row in set (0.00 sec)
但把SQL语句的子查询修改为以下的写法,执行效率就就像喝了可乐一样爽^0^:
select a.privilege_id from test2 as a inner join test1 as b on a.role_id = b.role_id and b.id=192;
看效果对比:
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.1.66 |
+-----------+
1 row in set (0.00 sec) mysql> explain select privilege_id from test2 where role_id in (select role_id from test1 where id=192);
+----+--------------------+-------+-------+---------------+---------+---------+-------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+---------+---------+-------+-------+-------------+
| 1 | PRIMARY | test2 | ALL | NULL | NULL | NULL | NULL | 12476 | Using where |
| 2 | DEPENDENT SUBQUERY | test1 | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+----+--------------------+-------+-------+---------------+---------+---------+-------+-------+-------------+
2 rows in set (0.00 sec) mysql> explain select a.privilege_id from test2 as a inner join test1 as b on a.role_id = b.role_id and b.id=192;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | b | const | PRIMARY | PRIMARY | 4 | const | 1 | |
| 1 | SIMPLE | a | ref | role_id | role_id | 4 | const | 32 | |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
2 rows in set (0.00 sec)
相信大家也能看到修改后跟修改前的差别了吧!
以下用版本为5.5的版本测试下:
mysql> select version();
+------------+
| version() |
+------------+
| 5.5.30-log |
+------------+
1 row in set (0.00 sec) mysql> explain select privilege_id from test2 where role_id in (select role_id from test1 where id=192);
+----+--------------------+-------+-------+---------------+---------+---------+-------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+---------+---------+-------+-------+-------------+
| 1 | PRIMARY | test2 | ALL | NULL | NULL | NULL | NULL | 12195 | Using where |
| 2 | DEPENDENT SUBQUERY | test1 | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+----+--------------------+-------+-------+---------------+---------+---------+-------+-------+-------------+
2 rows in set (0.03 sec) mysql> explain select a.privilege_id from test2 as a inner join test1 as b on a.role_id = b.role_id and b.id=192;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | b | const | PRIMARY | PRIMARY | 4 | const | 1 | |
| 1 | SIMPLE | a | ref | role_id | role_id | 4 | const | 32 | |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
2 rows in set (0.01 sec)
MySQL5.5的版本和5.1的情况一样,如果用类似的子查询,可能会存在性能问题
以下用版本为5.6的版本测试下:
mysql> select version();
+------------+
| version() |
+------------+
| 5.6.10-log |
+------------+
1 row in set (0.00 sec) mysql> explain select privilege_id from test2 where role_id in (select role_id from test1 where id=192);
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | test1 | const | PRIMARY | PRIMARY | 4 | const | 1 | NULL |
| 1 | SIMPLE | test2 | ref | role_id | role_id | 4 | const | 32 | NULL |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
2 rows in set (0.07 sec) mysql> explain select a.privilege_id from test2 as a inner join test1 as b on a.role_id = b.role_id and b.id=192;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | b | const | PRIMARY | PRIMARY | 4 | const | 1 | NULL |
| 1 | SIMPLE | a | ref | role_id | role_id | 4 | const | 32 | NULL |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
2 rows in set (0.04 sec)
看到的两种查询结果是一样高效的,从以上的案例可以看出,写通用且性能高的SQL相当重要,希望大家以后不要踩类似的坑@.@
总结:mysql5.6版本无论在性能还是功能上,已经比之前的版本提升了不少,是一个不错的选择,另外,sql语句写得不适当,会带来很严重的性能问题
作者:陆炫志 出处:xuanzhi的博客 http://www.cnblogs.com/xuanzhi201111 您的支持是对博主最大的鼓励,感谢您的认真阅读。本文版权归作者所有,欢迎转载,但请保留该声明。 |
SQL语句导致性能问题的更多相关文章
- 利用pl/sql执行计划评估SQL语句的性能简析
一段SQL代码写好以后,可以通过查看SQL的执行计划,初步预测该SQL在运行时的性能好坏,尤其是在发现某个SQL语句的效率较差时,我们可以通过查看执行计划,分析出该SQL代码的问题所在. 那么,作为 ...
- SQl语句查询性能优化
[摘要]本文从DBMS的查询优化器对SQL查询语句进行性能优化的角度出发,结合数据库理论,从查询表达式及其多种查询条件组合对数据库查询性能优化进行分析,总结出多种提高数据库查询性能优化策略,介绍索引的 ...
- mybatis的sql语句导致索引失效,使得查询超时
mybaitis书写sql需要特别注意where条件中的语句,否则将会导致索引失效,使得查询总是超时.如下语句会出现导致索引失效的情况: with test1 as (select count(C_F ...
- SQL语句导致cpu占用如此高
一般我们可以使用sql server自带的性能分析追踪工具sql profiler分析数据库设计所产生问题的来源,进行有针对性的处理.但我们也可以通过自己写SQL语句来有针对性的进行性能方面的查询.通 ...
- 提高SQL语句的性能
一.FROM子句中的表 FROM子表的安排或次序对性能有很大的影响,把较小的表放在前面,把较大的表放在后面,可以得到更高的效率. 二.WHERE子句中的次序 一般来自基表的字段放在结合操作的右侧,要被 ...
- mysql的sql语句的性能诊断分析
1> explain SQL,类似于Oracle中explain语句 例如:explain select * from nad_aditem; 2> select benchmark(co ...
- SQL 语句与性能之执行顺序
select * , t3.Name from t1 left join t2 on t1.sysno = t2.Asysno left join t3 on t3.sysno = t2.Bsysno ...
- SQL语句执行性能
通过设置STATISTICS我们可以查看执行SQL时的系统情况.选项有PROFILE,IO ,TIME.介绍如下: SET STATISTICS PROFILE ON:显示分析.编译和执行查询所需的时 ...
- SQL 语句与性能之联合查询和联合分类查询
select * from t1 left join t2 on t2.sysno =t1.ASysNo left join t3 on t3.sysno =t2.ASysNo left join t ...
随机推荐
- 在手机上点击input框时会放大页面
加上 <meta name="viewport" content="initial-scale=1.0, minimum-scale=1.0, maximum-s ...
- Ubuntu17安装Jenkins
Java安装 Jenkins基于Java, 所以需要先安装java. Linux下安装java只要配置java环境变量即可. 首先,解压java到相应目录,我一般习惯把安装的软件放到目录/usr/lo ...
- 利用Attribute和IErrorHandler处理WCF全局异常
在处理WCF异常的时候,有大概几种方式: 第一种是在配置文件中,将includeExceptionDetailInFaults设置为true <behavior name="servi ...
- 【设计模式】—— 迭代模式Iterator
前言:[模式总览]——————————by xingoo 模式意图 提供一个方法按顺序遍历一个集合内的元素,而又不需要暴露该对象的内部表示. 应用场景 1 访问一个聚合的对象,而不需要暴露对象的内部表 ...
- loj6253/luogu4062-Yazid的新生舞会
先考虑部分分(只有01/只有0~7)做法:枚举每个数,把和他相同的设为1,不同的设为-1,然后这个数作为众数贡献的个数就是区间和>0的个数 推着做,树状数组记前缀和<=x的区间的数量就可以 ...
- jQuery源码之 empty与html('')的区别
empty: function() { var elem, i = 0; for ( ; (elem = this[i]) != null; i++ ) { // Remove element nod ...
- 洛谷P4486 Kakuro
题意:你有一个棋盘,某些格子是限制条件,形如"从这里开始下面所有连续空格的和为a"或"从这里开始向右的所有连续空格之和为b"一个格子可以同时拥有两个限制条件. ...
- 【洛谷P1330】封锁阳光大学
题目大意:给定一个 N 个点,M 条边的无向图,现在要选出图中的一个顶点集合,使得集合种的顶点不直接相邻,且这张图的所有边都被该顶点集合覆盖,求该顶点集合大小的最小值,若不能完成覆盖,则输出 impo ...
- Java后台面试 常见问题
Java后台面试 常见问题 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米.百度.阿里.京东.新浪.CVTE.乐视家的研发岗offer.我找的是java后台开发,把常见的问题分享 ...
- Hbuild开发App入门
http://ask.dcloud.net.cn/article/89建议必看网站 http://www.html5plus.org/doc/h5p.html API下载地址