SQL优化目的:

降低响应时间
直接影响用户体验度

降低资源使用率
主要体现在IO和CPU上,网络、内存消耗

优化原则:

1.IN子查询改成JOIN
2.NOT IN子查询改成LEFT JOIN
3.消除无效子查询
4.禁用select *,只读取所需字段
5.LIMIT M, N 大分页修改成JOIN形式
6.大结果集 limit限制,where限制,分页读取
7.使用where xx IN (),IN子句中元素建议小于200
8.多表Join时,注意比较字段类型一致,避免隐式类型转换
9.Where子句右值都用单引号括起,避免隐式类型转换
10.Update/delete根据索引删除,禁用Update/delete … limit N结构SQL
11.禁止对索引列进行数值计算

1.类型转化(避免隐式的类型转换)

mysql> desc tb_shop_order
-> ;
+----------------------+----------------+------+-----+---------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+----------------+------+-----+---------------------+-----------------------------+
| id | varchar(60) | NO | PRI | NULL | |
| gorder_id | varchar(60) | NO | MUL | NULL | |
| product_type | char(4) | NO | MUL | NULL | |
| order_time | timestamp | NO | MUL | 0000-00-00 00:00:00 | |
| order_status | tinyint(2) | NO | MUL | NULL | |
| order_amount | decimal(12,2) | NO | | 0.00 | |
| save_amount | decimal(12,2) | NO | | 0.00 | |
| pay_amount | decimal(12,2) | NO | | 0.00 | |
| logistics_amount | decimal(12,2) | YES | | NULL | |
| fee | decimal(12,2) | NO | | 0.00 | |
| original_pay_amount | decimal(12,2) | NO | | 0.00 | |
| cost_amount | decimal(12,2) | NO | | 0.00 | |
| buy_account_id | varchar() | NO | MUL | NULL | |
| pre_close_time | timestamp | NO | MUL | 0000-00-00 00:00:00 | |
| update_time | timestamp | NO | MUL | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| settle_up | tinyint(1) | NO | MUL | NULL | |
| success_time | timestamp | NO | | 0000-00-00 00:00:00 | |
| merchant_id | int(10) | NO | MUL | NULL | |
| merchant_name | varchar(100) | NO | MUL | NULL | |
| merchant_account | varchar(100) | YES | | NULL | |
| merchant_tel | varchar(60) | YES | | NULL | |
| merchant_order_id | varchar(100) | YES | MUL | NULL | |
| merchant_amount | decimal(12,2) | YES | | NULL | |
| activity_id | int(10) | YES | | NULL | |
| activity_type | tinyint(2) | YES | | NULL | |
| order_desc | varchar(1000) | YES | | NULL | |
| remark | varchar(500) | YES | | NULL | |
| can_deliver | tinyint(1) | YES | | NULL | |
| can_settle_up | tinyint(1) | YES | | NULL | |
| can_refund | tinyint(1) | YES | | NULL | |
| misc | varchar(14100) | YES | | NULL | |
| key_words | varchar(200) | YES | | NULL | |
| delivery_begin_time | timestamp | NO | MUL | 0000-00-00 00:00:00 | |
| delivery_end_time | timestamp | NO | MUL | 0000-00-00 00:00:00 | |
| relation_id | varchar(60) | YES | | NULL | |
| order_ip | varchar(60) | YES | | NULL | |
| closed_reason | varchar(60) | YES | | NULL | |
| status_desc | varchar(60) | YES | | NULL | |
| note | varchar(5120) | YES | | NULL | |
| refund_amount | decimal(12,2) | NO | | 0.00 | |
| distributor_order_id | varchar(100) | NO | MUL | | |
+----------------------+----------------+------+-----+---------------------+-----------------------------+
41 rows in set (0.00 sec)

 定义: `buy_account_id` varchar(60) NOT NULL COMMENT '卡号',

mysql> explain select * from tb_shop_order where buy_account_id = 190000000033703177;
+----+-------------+---------------+------------+------+--------------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------+------------+------+--------------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | tb_shop_order | NULL | ALL | ix_order_accountid | NULL | NULL | NULL | 179981 | 10.00 | Using where |
+----+-------------+---------------+------------+------+--------------------+------+---------+------+--------+----------+-------------+
1 row in set, 3 warnings (0.00 sec)

改造之后:ref 走的是const,rows扫描的行数表少,不在是全表扫描了

mysql> explain select * from tb_shop_order where buy_account_id = '';
+----+-------------+---------------+------------+------+--------------------+--------------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------+------------+------+--------------------+--------------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | tb_shop_order | NULL | ref | ix_order_accountid | ix_order_accountid | 182 | const | 1418 | 100.00 | NULL |
+----+-------------+---------------+------------+------+--------------------+--------------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

原则:Where子句右值都用单引号括起,避免隐式类型转换!!!

2.字段计算(使用函数在字段上,不走索引)

mysql> explain select * from tb_shop_order where DATE_FORMAT (order_time,'%Y-%m-%d') = '2016-04-05';
+----+-------------+---------------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | tb_shop_order | NULL | ALL | NULL | NULL | NULL | NULL | 179981 | 100.00 | Using where |
+----+-------------+---------------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

改造之后:row 扫描的行数变少,不再是全表烧苗,而是范围扫描,而且

Extra Using index

这是性能很高的一种情况。当查询所需的数据可以直接从索引树中检索到时,就会出现。

mysql> explain select * from tb_shop_order where order_time > '2016-04-05 00:00:00' and order_time < '2016-04-05 23:59:59';
+----+-------------+---------------+------------+-------+----------------+----------------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------+------------+-------+----------------+----------------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | tb_shop_order | NULL | range | ix_order_otime | ix_order_otime | 4 | NULL | 89 | 100.00 | Using index condition |
+----+-------------+---------------+------------+-------+----------------+----------------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

3.避免全表扫描更新

(1) update XXX set batch = '2016-09-27 16:21:01'

where batch = '1970-01-01 08:00:30';

(2) delete from XXX where batch   <   '2016-09-26 16:21:00';

改造成根据主键批量更新:

select min(pk), max(pk) from table where batch = '1970-01-01 08:00:30';

Update … where batch = '1970-01-01 08:00:30' and pk >= min and pk < i
Update … where batch = '1970-01-01 08:00:30' and pk >= i and pk < j
Update … where batch = '1970-01-01 08:00:30' and pk >= j and pk < max

4.字段传值正确性

错误的拼接:

select * from tb_shop_order where order_time > CONCAT('2016-04-05 00:00:00','00:00:00') and order_time < CONCAT('2016-04-05 23:59:59','00:00:00');

select * from tb_shop_order where order_time > '2016-04-05 00:00:00' and order_time < '2016-04-05 23:59:59./';

5. in OR not in优化

mysql> explain select * from tb_shop_order where buy_account_id  ='' and product_type in (select product_type from tb_shop_gorder );
+----+-------------+----------------+------------+------+----------------------------------+--------------------+---------+-------------------------------+-------+----------+----------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------------+------------+------+----------------------------------+--------------------+---------+-------------------------------+-------+----------+----------------------------------------+
| 1 | SIMPLE | tb_shop_order | NULL | ref | ix_order_accountid,ix_order_prod | ix_order_accountid | 182 | const | 6 | 100.00 | NULL |
| 1 | SIMPLE | tb_shop_gorder | NULL | ref | ix_gorder_ptype | ix_gorder_ptype | 12 | lp.tb_shop_order.product_type | | 100.00 | Using index; FirstMatch(tb_shop_order) |
+----+-------------+----------------+------------+------+----------------------------------+--------------------+---------+-------------------------------+-------+----------+----------------------------------------+
2 rows in set, 1 warning (0.00 sec)

改造后:

mysql> explain select t1.* from tb_shop_order t1 INNER JOIN tb_shop_gorder t2 on t1.product_type = t2.product_type  where t1.buy_account_id  ='';
+----+-------------+-------+------------+------+----------------------------------+--------------------+---------+--------------------+-------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+----------------------------------+--------------------+---------+--------------------+-------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | ref | ix_order_accountid,ix_order_prod | ix_order_accountid | 182 | const | 6 | 100.00 | NULL |
| 1 | SIMPLE | t2 | NULL | ref | ix_gorder_ptype | ix_gorder_ptype | 12 | lp.t1.product_type | 10333 | 100.00 | Using index |
+----+-------------+-------+------------+------+----------------------------------+--------------------+---------+--------------------+-------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)
mysql> explain select * from tb_shop_order where buy_account_id  ='' and product_type not in (select product_type from tb_shop_gorder );+----+--------------------+----------------+------------+----------------+--------------------+--------------------+---------+-------+-------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+----------------+------------+----------------+--------------------+--------------------+---------+-------+-------+----------+-------------+
| 1 | PRIMARY | tb_shop_order | NULL | ref | ix_order_accountid | ix_order_accountid | 182 | const | 6 | 100.00 | Using where |
| 2 | DEPENDENT SUBQUERY | tb_shop_gorder | NULL | index_subquery | ix_gorder_ptype | ix_gorder_ptype | 12 | func | 10333 | 100.00 | Using index |
+----+--------------------+----------------+------------+----------------+--------------------+--------------------+---------+-------+-------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

改造后:

mysql> explain select t1.* from tb_shop_order t1 LEFT  JOIN tb_shop_gorder t2 on t1.product_type = t2.product_type  where t1.buy_account_id  ='' and t2.product_type IS NULL;
+----+-------------+-------+------------+------+--------------------+--------------------+---------+--------------------+-------+----------+--------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+--------------------+--------------------+---------+--------------------+-------+----------+--------------------------------------+
| 1 | SIMPLE | t1 | NULL | ref | ix_order_accountid | ix_order_accountid | 182 | const | 6 | 100.00 | NULL |
| 1 | SIMPLE | t2 | NULL | ref | ix_gorder_ptype | ix_gorder_ptype | 12 | lp.t1.product_type | 10333 | 100.00 | Using where; Not exists; Using index |
+----+-------------+-------+------------+------+--------------------+--------------------+---------+--------------------+-------+----------+--------------------------------------+
2 rows in set, 1 warning (0.00 sec)

mysql优化总结的更多相关文章

  1. MySQL优化聊两句

    原文地址:http://www.cnblogs.com/verrion/p/mysql_optimised.html MySQL优化聊两句 MySQL不多介绍,今天聊两句该如何优化以及从哪些方面入手, ...

  2. 0104探究MySQL优化器对索引和JOIN顺序的选择

    转自http://www.jb51.net/article/67007.htm,感谢博主 本文通过一个案例来看看MySQL优化器如何选择索引和JOIN顺序.表结构和数据准备参考本文最后部分" ...

  3. mysql 优化

    1.存储过程造数据 CREATE DEFINER=`root`@`localhost` PROCEDURE `generate_test_data`(`n` int) begin declare i ...

  4. mysql优化笔记之分页

    过年闲得蛋疼,于是看看mysql优化,看了网上好多关于分页的优化方法,但是呢,我亲自试上一把的时候,没有出现他们说的现象...难道是我的机器问题么? 下面看看我的实践记录,希望看到的加入进来交流一下O ...

  5. MySQL优化概述

    一. MySQL优化要点 MySQL优化是一门复杂的综合性技术,主要包括: 1 表的设计合理化(符合 3NF,必要时允许数据冗余) 2.1 SQL语句优化(以查询为主) 2.2 适当添加索引(主键索引 ...

  6. MySQL优化实例

    这周就要从泰笛离职了,在公司内部的wiki上,根据公司实际的项目,写了一些mysql的优化方法,供小组里的小伙伴参考下,没想到大家的热情很高,还专门搞了个ppt讲解了一下. 举了三个大家很容易犯错的地 ...

  7. Mysql优化系列(2)--通用化操作梳理

    前面有两篇文章详细介绍了mysql优化举措:Mysql优化系列(0)--总结性梳理Mysql优化系列(1)--Innodb引擎下mysql自身配置优化 下面分类罗列下Mysql性能优化的一些技巧,熟练 ...

  8. mysql优化记录

    老板反应项目的反应越来越慢,叫优化一下,顺便学习总结一下mysql优化. 不同引擎的优化,myisam读的效果好,写的效率差,使用场景 非事务型应用只读类应用空间类应用 Innodb的特性,innod ...

  9. mysql 优化实例之索引创建

    mysql 优化实例之索引创建 优化前: pt-query-degist分析结果: # Query 23: 0.00 QPS, 0.00x concurrency, ID 0x78761E301CC7 ...

  10. MySQL优化的奇技淫巧之STRAIGHT_JOIN

    原文地址:http://huoding.com/2013/06/04/261 问题 通过「SHOW FULL PROCESSLIST」语句很容易就能查到问题SQL,如下: SELECT post.* ...

随机推荐

  1. Jquery的初识

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. std::bind(二)

    bind - boost 头文件: boost/bind.hpp bind 是一组重载的函数模板. 用来向一个函数(或函数对象)绑定某些参数. bind的返回值是一个函数对象. 它的源文件太长了. 看 ...

  3. linux环境下安装sphinx中文支持分词搜索(coreseek+mmseg)

     linux环境下安装sphinx中文支持分词搜索(coreseek+mmseg) 2013-11-10 16:51:14 分类: 系统运维 为什么要写这篇文章? 答:通过常规的三大步(./confi ...

  4. 修改更新源sources.list,提高软件下载安装速度(提供Kali 2.0 更新源)

    1.切换到root用户(如果已经是root用户就直接看第二步) dnt@HackerKali:~$ su 密码: 2.用文本编辑器打开sources.list,手动添加下面的更新源 root@Hack ...

  5. tomcat架构

    很多开源应用服务器都是集成tomcat作为web container的,而且对于tomcat的servlet container这部分代码很少改动.这样,这些应用服务器的性能基本上就取决于Tomcat ...

  6. DedeCMS V5.7 Dialog目录下配置文件XSS漏洞

    漏洞地址及证明:/include/dialog/config.php?adminDirHand="/></script><script>alert(1);< ...

  7. python读写操作文件

    with open(xxx,'r,coding='utf-8') as f:   #打开文件赋值给F ,并且执行完了之后不需要 f.close(). 在Python 2.7 及以后,with又支持同时 ...

  8. 快速搭建ssh(最终版)

    一个月又忘了.还是做个笔记.自己看下就能想起来... 1.在MyEclipse中新建web Project 2.首先整合struts

  9. dao、domain、service、web、vo、Model这些层的功能是什么

    这些层次都是用来管理不同的代码,让代码具有更好的维护性.开发中一般采用三层架构即MVC的模式来进行开发,M:代表model,可以理解为javaBean:V:代表view,可以理解为jsp:c:代表co ...

  10. 各种工具使用手册:http://www.itshouce.com.cn/linux/linux-tcpdump.html 关于tcpdump!!!!

    各种工具使用手册:http://www.itshouce.com.cn/linux/linux-tcpdump.html 关于tcpdump!!!! 实用tcpdump命令 //查看本机与mysql的 ...