mysql优化总结
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优化总结的更多相关文章
- MySQL优化聊两句
原文地址:http://www.cnblogs.com/verrion/p/mysql_optimised.html MySQL优化聊两句 MySQL不多介绍,今天聊两句该如何优化以及从哪些方面入手, ...
- 0104探究MySQL优化器对索引和JOIN顺序的选择
转自http://www.jb51.net/article/67007.htm,感谢博主 本文通过一个案例来看看MySQL优化器如何选择索引和JOIN顺序.表结构和数据准备参考本文最后部分" ...
- mysql 优化
1.存储过程造数据 CREATE DEFINER=`root`@`localhost` PROCEDURE `generate_test_data`(`n` int) begin declare i ...
- mysql优化笔记之分页
过年闲得蛋疼,于是看看mysql优化,看了网上好多关于分页的优化方法,但是呢,我亲自试上一把的时候,没有出现他们说的现象...难道是我的机器问题么? 下面看看我的实践记录,希望看到的加入进来交流一下O ...
- MySQL优化概述
一. MySQL优化要点 MySQL优化是一门复杂的综合性技术,主要包括: 1 表的设计合理化(符合 3NF,必要时允许数据冗余) 2.1 SQL语句优化(以查询为主) 2.2 适当添加索引(主键索引 ...
- MySQL优化实例
这周就要从泰笛离职了,在公司内部的wiki上,根据公司实际的项目,写了一些mysql的优化方法,供小组里的小伙伴参考下,没想到大家的热情很高,还专门搞了个ppt讲解了一下. 举了三个大家很容易犯错的地 ...
- Mysql优化系列(2)--通用化操作梳理
前面有两篇文章详细介绍了mysql优化举措:Mysql优化系列(0)--总结性梳理Mysql优化系列(1)--Innodb引擎下mysql自身配置优化 下面分类罗列下Mysql性能优化的一些技巧,熟练 ...
- mysql优化记录
老板反应项目的反应越来越慢,叫优化一下,顺便学习总结一下mysql优化. 不同引擎的优化,myisam读的效果好,写的效率差,使用场景 非事务型应用只读类应用空间类应用 Innodb的特性,innod ...
- mysql 优化实例之索引创建
mysql 优化实例之索引创建 优化前: pt-query-degist分析结果: # Query 23: 0.00 QPS, 0.00x concurrency, ID 0x78761E301CC7 ...
- MySQL优化的奇技淫巧之STRAIGHT_JOIN
原文地址:http://huoding.com/2013/06/04/261 问题 通过「SHOW FULL PROCESSLIST」语句很容易就能查到问题SQL,如下: SELECT post.* ...
随机推荐
- API与软件架构
http://blog.csdn.net/horkychen/article/details/46612899 从架构设计的角度来看(所谓的组成论),软件系统就是模块和接口. 模块(层次/组件)决定分 ...
- Android应用目录结构分析
一.手动创建android项目 手动创建一个Android项目,命名为HelloWorld,命令如下: android create project -n HelloWorld -t 1 -p E:/ ...
- httpd设置HTTPS双向认证
去年用tomcat.jboss配置过HTTPS双向认证,那时候主要用的是JDK自带的keytool工具.这次是用httpd + openssl,区别比较大 在网上搜索了很多文章,发现全面介绍的不多,或 ...
- js中对象概念的声明
- tp auth 转载保存
PS:最近需要做一个验证用户权限的功能,在官方和百度看了下,发现大家都是用auth来做验证,官方有很多auth的使用教程,但是都不全面,我也提问了几个关于auth的问题 也没人来回答我,无奈只好一步步 ...
- ssh框架整合完整版
1.导入jar包 可以在src下添加一个log4j.properties文件来记录日志 2.加入实体类+映射文件 映射:从类入手class+属性 a.映射的头文件在:hibernate3.jar--& ...
- python -os、sys
个人还不是很懂 os操作文件目录.sys针对系统环境的交互.大概是这样 使用os.system函数运行其他程序 os模块中的system()函数可以方便地运行其他程序或者脚本.其函数原型如下所示. o ...
- spring bean id和bean name的区别
今天在分析问题时发现一个大家平时都不太注意的spring 配置问题,发出来分享下: 首先澄清一个概念: 同名bean:多个bean 有相同的 name 或者 id,称之为同名bean <bean ...
- jquery json ajax -2
如果使用的是虚拟空间, 那么你不能操纵/配置服务器上的php.ini配置文件 但是可以在自己的php文件中, 通过ini_set(...), 和一些对应的函数, 去重置(临时的,仅在当前文件中生效的) ...
- PHP Document 注释标记及规范 && PHP命名规范
注释标记 @access 使用范围:class,function,var,define,module 该标记用于指明关键字的存取权限:private.public或proteced @author 指 ...