前阵子,突然收到服务器的报警信息,于是上服务器找问题,我擦,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语句导致性能问题的更多相关文章

  1. 利用pl/sql执行计划评估SQL语句的性能简析

    一段SQL代码写好以后,可以通过查看SQL的执行计划,初步预测该SQL在运行时的性能好坏,尤其是在发现某个SQL语句的效率较差时,我们可以通过查看执行计划,分析出该SQL代码的问题所在.  那么,作为 ...

  2. SQl语句查询性能优化

    [摘要]本文从DBMS的查询优化器对SQL查询语句进行性能优化的角度出发,结合数据库理论,从查询表达式及其多种查询条件组合对数据库查询性能优化进行分析,总结出多种提高数据库查询性能优化策略,介绍索引的 ...

  3. mybatis的sql语句导致索引失效,使得查询超时

    mybaitis书写sql需要特别注意where条件中的语句,否则将会导致索引失效,使得查询总是超时.如下语句会出现导致索引失效的情况: with test1 as (select count(C_F ...

  4. SQL语句导致cpu占用如此高

    一般我们可以使用sql server自带的性能分析追踪工具sql profiler分析数据库设计所产生问题的来源,进行有针对性的处理.但我们也可以通过自己写SQL语句来有针对性的进行性能方面的查询.通 ...

  5. 提高SQL语句的性能

    一.FROM子句中的表 FROM子表的安排或次序对性能有很大的影响,把较小的表放在前面,把较大的表放在后面,可以得到更高的效率. 二.WHERE子句中的次序 一般来自基表的字段放在结合操作的右侧,要被 ...

  6. mysql的sql语句的性能诊断分析

    1> explain SQL,类似于Oracle中explain语句 例如:explain select * from nad_aditem; 2> select benchmark(co ...

  7. SQL 语句与性能之执行顺序

    select * , t3.Name from t1 left join t2 on t1.sysno = t2.Asysno left join t3 on t3.sysno = t2.Bsysno ...

  8. SQL语句执行性能

    通过设置STATISTICS我们可以查看执行SQL时的系统情况.选项有PROFILE,IO ,TIME.介绍如下: SET STATISTICS PROFILE ON:显示分析.编译和执行查询所需的时 ...

  9. SQL 语句与性能之联合查询和联合分类查询

    select * from t1 left join t2 on t2.sysno =t1.ASysNo left join t3 on t3.sysno =t2.ASysNo left join t ...

随机推荐

  1. Vue-router的基本用法

    刚学习vue不久,就接触了路由这个好东西.下面简单聊聊vue-router的基本用法. 一.路由的概念 路由,其实就是指向的意思,当我点击页面上的home按钮时,页面中就要显示home的内容,如果点击 ...

  2. pgm3

    这部分主要讨论了一些概念性的东西.一个是常用的 local probabilistic models,一个是如何用 template-based representation. 这部分主要是一些概念, ...

  3. BZOJ2729 HNOI2012排队(组合数学+高精度)

    组合入门题.高精度入门题. #include<iostream> #include<cstdio> #include<cstdlib> #include<cs ...

  4. Ubuntu 16.04搭建LAMP开发环境

    基本设置 1.配置网络环境 管理员给分配了一个静态IP,所以还需要进一步配置网络环境 配置DNS:右上角网络连接->编辑链接->有线连接1->IPv4设置->DNS服务器:20 ...

  5. fgt2eth Script

    fgt2eth Script explanation_on_how_to_packet_capture_for_only_certain_TCP_flags_v2.txt Packet capture ...

  6. MT【173】齐次消元单变量

    已知$x\ge0,x^2+(y-2)^2=1,W=\dfrac{3x^2+2\sqrt{3}xy+5y^2}{x^2+y^2}$,求$W$的最值. 提示:$x\ne0$时,设$t=\dfrac{y}{ ...

  7. 【arc093f】Dark Horse(容斥原理,动态规划,状态压缩)

    [arc093f]Dark Horse(容斥原理,动态规划,状态压缩) 题面 atcoder 有 \(2^n\) 名选手,编号为 \(1\) 至 \(2^n\) .现在这 \(2^n\) 名选手将进行 ...

  8. 走楼梯(walk) 解题报告

    走楼梯(walk) 题意 给一个长为\(n(1\le n\le 10^5)\)序列\(\{a\}\),每次从中间挖掉\([l,r]\),然后询问最长上升子序列,强制在线. 有一档分是30000和离线, ...

  9. luogu3778/bzoj4898 商旅 (floyd+分数规划+spfa)

    首先floyd求出来每两点间的最短距离,然后再求出来从某点买再到某点卖的最大收益 问题就变成了找到一个和的比值最大的环 所以做分数规划,二分出来那个答案r,把边权变成w[i]-r*l[i],再做spf ...

  10. IIS并发连接数和数据库连接池

    一.数据库连接池 1.报错: 超时时间已到.超时时间已到,但是尚未从池中获取连接.出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小. 2.问题分析: 问题的原因是与数据库的连接没有显示关 ...