本文总结了一些工作常见的sql优化例子,虽然比较简单,但很实用,希望对大家有所帮助。sql优化一般分为两类,一类是sql本身的优化,如何走到合适的索引,如何减少排序,减少逻辑读;另一类是sql本身没有优化余地,需要结合业务场景进行优化。即在满足业务需求的情况下对sql进行改造,已提高sql执行速度,减少响应时间。

例子1:

SELECT ID FROM SENDLOG WHERE TO_DAYS(NOW())-TO_DAYS(GMT_CREATE) > 7;

问题:对索引列GMT_CREATE进行了运算,无法使用索引

优化后sql:
select id from sendlog where gmt_create < now() - 7
 
例子2:

SELECT * FROM SENDLOG where result =  and gmt_create > '2013-10-29 12:40:44' limit 2000;

问题:result列含有索引,但mysql执行计划没有用到。

分析:result类型为char,传递的值1为整型,数据类型不一致,导致没法用索引,对于时间类型gmt_create > '2013-10-29 12:40:44',可以直接使用。

优化后sql:

SELECT * FROM SENDLOG where result = '1' and gmt_create > '2013-10-29 12:40:44' limit 2000;

例子3:

场景:获取某个卖家未读的消息。

select count(*) from mc_msg where receiver='sun098' and status='UNREAD' and title is not null;

问题:有时候db负载飙高,sql响应时间变慢。

分析:导致db负载飙高的原因是多个大卖家并发查询的时,cpu和逻辑读增加,load飙高。由于receiver,status已有索引,sql本身已经没有优化空间,了解业务后发现其实业务不需要精确值,如果大于99条,页面就直接显示为99+

优化后sql:

select count(*) from (select id from mc_msg where receiver='sun098' and status='UNREAD' and title is not null limit 100) a;

例子4:

场景:查看历史订单留言记录,未读留言的放在前面,已读的放在后面,并且按时间递减排序

select * from(
select ID,GMT_CREATE,GMT_MODIFIED,SENDER_ALI_ID,RECEIVER_ALI_ID,UNREAD_COUNT,STATUS,LAST_MESSAGE_ID,RELATION_ID,SELLER_ADMIN_SEQ,IS_READ 
from message_relation_sender
WHERE SENDER_ALI_ID = 119545671  and UNREAD_COUNT > 0 
order by LAST_MESSAGE_ID desc) m 
union all 
select * from(
select ID,GMT_CREATE,GMT_MODIFIED,SENDER_ALI_ID,RECEIVER_ALI_ID,UNREAD_COUNT,STATUS,LAST_MESSAGE_ID,RELATION_ID,SELLER_ADMIN_SEQ,IS_READ from message_relation_sender
WHERE SENDER_ALI_ID = 119545671  and UNREAD_COUNT = 0 
order by LAST_MESSAGE_ID desc) n limit 5000,15;
 
分析:
(1)unread_count表示未读的订单留言记录数目;
(2)第一个子查询获取未读留言记录,第二子查询获取已读留言记录;
(3)LAST_MESSAGE_ID 递增,最新的订单留言,LAST_MESSAGE_ID最大。
(4)limit 5000,15是分页查询
这里使用union all,主要特点在于union all 不对结果集排序,直接合并,达到了“未读留言的放在前面,已读的放在后面”的效果,但同时也造成了两次扫描索引的结果,每个子查询都需要排序;而且union all还会产生临时表,执行代价会更大。
 
优化:
这里看到unread_count实际值对这个查询没有实际意义,我们只需要区分已读和未读即可。由于sql本身已经没有优化余地,考虑对表结构进行修改,加一个字段is_read,表示已读和未读。is_read=2表示未读;is_read=1表示已读。通过组合索引(SENDER_ALI_ID,is_read, LAST_MESSAGE_ID),既可以完成过滤,还可以完成排序。
 
优化后sql:
select ID,GMT_CREATE,GMT_MODIFIED,SENDER_ALI_ID,RECEIVER_ALI_ID,UNREAD_COUNT,STATUS,LAST_MESSAGE_ID,RELATION_ID,SELLER_ADMIN_SEQ,IS_READ from message_relation_sender
where SENDER_ALI_ID = 119545671  order by is_read desc, LAST_MESSAGE_ID desc limit 5000,15
 
第二次优化:
由于索引不包含所有的返回字段,因此需要回表,而mysql对于limit 5000,15的查询却需要返回5015次,这种无效的返回很影响查询效率。

分页的优化写法:

select t1.ID,GMT_CREATE,GMT_MODIFIED,SENDER_ALI_ID,RECEIVER_ALI_ID,UNREAD_COUNT,STATUS,LAST_MESSAGE_ID,RELATION_ID,SELLER_ADMIN_SEQ,IS_READ from message_relation_sender t1,
(select id 
 from message_relation_sender
 where SENDER_ALI_ID = 119545671 order by is_read desc, LAST_MESSAGE_ID desc limit 5000,15
)t2 where t1.id = t2.id
 
分析:由于id是主键,不需要回表,通过连接查询,最终只需要15次回表即可。

mysql优化案例分析的更多相关文章

  1. mysql优化案例

    MySQL优化案例 Mysql5.1大表分区效率测试 Mysql5.1大表分区效率测试MySQL | add at 2009-03-27 12:29:31 by PConline | view:60, ...

  2. MySQL死锁案例分析与解决方案

    MySQL死锁案例分析与解决方案 现象: 数据库查询: SQL语句分析:  mysql. 并发delete同一行记录,偶发死锁.   delete from x_table where id=?   ...

  3. MySQL优化 - 性能分析与查询优化(转)

    出处:  MySQL优化 - 性能分析与查询优化 优化应贯穿整个产品开发周期中,比如编写复杂SQL时查看执行计划,安装MySQL服务器时尽量合理配置(见过太多完全使用默认配置安装的情况),根据应用负载 ...

  4. MySQL的索引单表优化案例分析

    建表 建立本次优化案例中所需的数据库及数据表 CREATE DATABASE db0206; USE db0206; CREATE TABLE `db0206`.`article`( `id` INT ...

  5. SQL性能优化案例分析

    这段时间做一个SQL性能优化的案例分析, 整理了一下过往的案例,发现一个比较有意思的,拿出来给大家分享. 这个项目是我在项目开展2期的时候才加入的, 之前一期是个金融内部信息门户, 里面有个功能是收集 ...

  6. MySQL优化 - 性能分析与查询优化

    优化应贯穿整个产品开发周期中,比如编写复杂SQL时查看执行计划,安装MySQL服务器时尽量合理配置(见过太多完全使用默认配置安装的情况),根据应用负载选择合理的硬件配置等. 1.性能分析 性能分析包含 ...

  7. mysql优化:explain分析sql语句执行效率

    Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好的优 ...

  8. mysql优化–explain分析sql语句执行效率

    Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好的优 ...

  9. Mysql之案例分析(一)

    可见性分析 CREATE TABLE `t` ( `id` int(11) NOT NULL, `k` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGIN ...

随机推荐

  1. jsp错误路径跳转设置

    <error-page><error-code>400</error-code><location>/king.html</location> ...

  2. 2016暑假多校联合---Substring(后缀数组)

    2016暑假多校联合---Substring Problem Description ?? is practicing his program skill, and now he is given a ...

  3. Scalaz(24)- 泛函数据结构: Tree-数据游览及维护

    上节我们讨论了Zipper-串形不可变集合(immutable sequential collection)游标,在串形集合中左右游走及元素维护操作.这篇我们谈谈Tree.在电子商务应用中对于xml, ...

  4. Java自定义一个字典类(Dictionary)

    标准Java库只包含Dictionary的一个变种,名为:Hashtable.(散列表) Java的散列表具有与AssocArray相同的接口(因为两者都是从Dictionary继承来的).但有一个方 ...

  5. CentOS系统Kernel panic - not syncing: Attempted to kill init

    结果启动虚拟机出现如下问题: Kernel panic - not syncing: Attempted to kill init     解决方法: 系统启动的时候,按下'e'键进入grub编辑界面 ...

  6. 给你推荐10款优秀的 HTML5 动画工具

    HTML5 在过去三年快速增长,已经成为 Web 开发人员最喜欢的编程语言之一.强大的编程语言拥有开发更好的网页应用的能力. HTML5 中引入的新技术都非常好,像 Chrome.Firefox.Sa ...

  7. HtmlEncode和JavaScriptEncode(预防XSS)

    在数据添加到DOM时候,我们可以需要对内容进行HtmlEncode或JavaScriptEncode,以预防XSS攻击. JavaScriptEncode 使用“\”对特殊字符进行转义,除数字字母之外 ...

  8. 关于sharepoint2013的SPUtility.GetGenericSetupPath()方法过期解决办法

    有个时候需要读取layouts下的xml文件,因此需要知道路径,以前在SP2010用的SPUtility.GetGenericSetupPath()方法获取.现在SP2013提示过期否决 看2个结构分 ...

  9. crm2013关于contentIFrame不能使用

    在CRM2011里面,我们可以在页面的控制台里面输入: contentIFrame.Xrm.Page.data.entity.getEntityName(); contentIFrame.Xrm.Pa ...

  10. SharePoint 2010 站点附加数据升级到SP2013

    首先,去SharePoint 2010的数据库服务器上,找到站点的数据库,备份.还原到SharePoint 2013环境中: 如果不知道数据库服务器是哪台,可以通过服务器场上的服务器查看: 如果不知道 ...