转http://www.taobaodba.com/html/851_sql优化的一些总结.html

SQL的优化是DBA日常工作中不可缺少的一部分,记得在学生时期,曾经在ITPUB上看到一篇帖子,当时楼主在介绍SQL优化的时候,用一个公式来讲解他在做sql优化的时候遵循的原则:

T=S/V(T代表时间,S代表路程,V代表速度)

S指SQL所需访问的资源总量,V指SQL单位时间所能访问的资源量,T自然就是SQL执行所需时间了;我们为了获得SQL最快的执行时间,可以根据公式定义上去反推:

  1. 在S不变的情况下,我们可以提升V来降低T:通过适当的索引调整,我们可以将大量的速度较慢的随机IO转换为速度较快的顺序IO;通过提升服务器的内存,使得将更多的数据放到内存中,会比数据放到磁盘上会得到明显的速度提升;采用电子存储介质进行数据存储和读取的SSD,突破了传统机械硬盘的性能瓶颈,使其拥有极高的存储性能;在提升V上我们可以采用较高配置的硬件来完成速度的提升;
  2. 在V不变的情况下,我们可以减小S来降低T:这是SQL优化中非常核心的一个环节,在减小S环节上,DBA可以做的可以有很多,通常可以在查询条件中建立适当的索引,来避免全表扫描;有时候可以改写SQl,添加一些适当的提示符,来改变SQL的执行计划,使SQL以最少的扫描路径完成查询;当这些方法都使用完了之后,你是否还有其他方案来优化喃?在阿里系的DBA职位描述中有条就是要求DBA需要深入的了解业务,当DBA深入的了解业务之后,这个时候能站在业务上,又站DB角度上考虑,这个时候在去做优化,有时候能达到事半功倍的效果。

案例一:通过降低S,来提升T

原理介绍:
我们知道B+索引叶子节点的值是按照索引字段升序的,比如我们对(nick,appkey)两个字段做了索引,那么在索引中的则是按照nick,appkey的升序排列;如果我们现在的一条sql:
select count(distinct nick) from xxxx_nickapp_09_29;
用于查询统计某天日志表中的UV,优化器选择了该表上索引ind_nick_appkey(nick,appkey)来完成查询,则开始从nick1开始一条条扫描下来,直到扫描到最后一个nick_n,那么中间过程会扫描很多重复的nick(最左边普通扫描),如果我们能够跳过中间重复的nick,则性能会优化非常多(最右边的松散扫描):

从上面的可以得到一个结论:

如果这条统计uv的sql能够按照右边的loose index scan的方式来扫描话,会大大的减小我们上面提到的S;所以需要通过改写sql来达到伪loose index scan:(MySql优化器不能直接的对count(distinct column)做优化)

root@DB 09:41:30>select count(*) from ( select distinct(nick) from xxxx_nickapp_09_29)t ;
+———-+
| count(*) |
+———-+
| 806934 |
+———-+
Sql内查询中先选出不同的nick,最后在外面套一层count,就可以得到nick的distinct值总和;
最重要的是在子查询中:select distinct(nick) 实现了上图中的伪loose index scan,优化器在这个时候的执行计划为Using index for group-by ,这样mysql就把distinct优化为group by,首先利用索引来分组,然后扫描索引,对需要的nick只扫描一条记录。

真实案例:

该案例选自我们的一个线上的生产系统,该系统每天有大量的日志数据入库,单表的容量在10G-50G之间,然后做汇总分析,计算日志数据中的uv就是其中一个逻辑,sql如下:

select count(distinct nick) from xxxx_nickapp_09_29;

即使在_xxxx分表上加上nick的索引,通过查看执行计划,为全索引扫描,由于单表的数据量过大,sql在执行的时候,会对整个服务器带来抖动,需要对原来的SQL进行改写,使其支持loose index scan;

优化前:

root@DB 09:41:30>select count(distinct nick) from xxxx_nickapp_09_29;
+———-+
| count(*) |
+———-+
| 806934 |

1 row in set (52.78 sec)
执行一次sql需要花费52.78s

优化后:

root@DB 09:41:30>select count(*) from ( select distinct(nick) from xxxx_nickapp_09_29)t ;

+———-+
| count(*) |
+———-+
| 806934 |
+———-+
1 row in set (5.81 sec)

由52.78秒降至5.81秒,速度提升了差不多10倍;

查看SQL的执行计划:

优化写法:

root@DB 09:41:30>explain select count(*) from ( select distinct(nick) from xxxx_nickapp_09_29)t ;

+—-+————-+——————————+——-+—————+———————————+———+—–
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+——————————+——-+—————+———————————+———+—–
| 1 | SIMPLE | xxxx_nickapp_09_29 | range | NULL |ind_nick_appkey | 67 | NULL | 2124695 | Using index for group-by |
+—-+————-+——————————+——-+—————+———————————+———+—–
原始写法:
root@DB 09:41:50>explain select count(distinct nick) from xxxx_nickapp_09_29;
+—-+————-+——————————+——-+—————+—————————-+———+——+–
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+——————————+——-+—————+—————————-+———+——+–
| 1 | SIMPLE | xxxx_nickapp_09_29 | index | NULL | ind_nick_appkey | 177 | NULL | 19546123 | Using index |
+—-+————-+——————————+——-+————–+—————————-+———+——+–

可以看到我们的路程由19546123减小到2124695,减小了9倍多.^_^

案例二:结合业务递增的写入特点,巧妙优化UV统计count(*)

有时候觉得,优化一条sql的最高境界就是让这sql能够从把这条从系统中拿掉,不管怎样,这些都是建立在你足够的了解业务上,就能够推动一些业务产品的升级或者下线,这样的DBA你能做到吗?

下面看一个案例:应用每天都会对入库的分表统计一个总数:select count(*) from xx_01_01;
随着单表的数据量越来越大(单表在20G左右),每次进行count的时候,速度越来越慢,同时需要扫描较多的数据页块,导致整个数据库性能的抖动,通过分析业务的特点,由于每张表采用自增id的方式进行插入,并且没有数据的删除,所以统计全表的总数就可以变通一下:

所以这条sql:select count(*) from xx_01_01;
可以变通为: select max(id)-min(id)+1 from xx_01_01;
执行速度可以得到质的飞跃 ^_^.

案例三:通过提升V,来降低T—随机IO  VS  顺序IO

在前面我们提到,提升V的一些方法,通常可以采用提升服务器硬件的方式来达到,但是很多中小型企业来说,现在比较高的成本对于他们来说还是望尘莫及,同时没有成熟的使用经验,对于他们可能还是一件坏事情。总的来说,你的服务器硬件无论在牛,如果SQL写的烂,索引建的不好,那还是不行的。

真实线上案例:在我们的一个核心产品库上,承载着非常大量的随机读,就叫它读库好了。一天读库的load非常的高,通过慢日志发现,有一条sql频繁的出现在慢日中,这条sql的查询条件很复杂,同时该表上的类似相同的索引也非常的多,当时是怀疑索引走错,通过explain 来查看SQL的执行计划:发现执行计划中的using where代表查询回表了,同时由于回表的记录rows较大,所以带来了大量的随机IO:

所以我们只需要在原来的索引冗余掉is_detail字段就可以通过覆盖索引的方法优化掉该sql,避免了查询回表而导致的随机io,用顺序io替换了原来的随机io,SQL的执行速度得到极大提升:(下图会去掉is_detail字段的测试)

总结:SQL优化是很有趣的一件事情,我们在日常工作中可以按照t=s/v的思路来进行优化,也许你第一次运用它的时候有些陌生,但是只要不断的练习,善于总结,你也会发现其中的规律,真是妙哉妙哉。还有一点很重要的是,你的SQL优化不要脱离实际业务,也许你在哪里优化一条sql花了1个小时,但是去和开发同学讨论优化成果的时候,开发同学说这条sql其实可以下线了,那时候真的哭笑不得了 ^_^.

转载于:https://www.cnblogs.com/goto/archive/2012/12/20/2826013.html

SQL优化的一些总结相关推荐

  1. 史上最全SQL优化方案(二)

    接上篇!! 4 基础优化 a 优化思路 定位问题点吮吸:硬件–>系统–>应用–>数据库–>架构(高可用.读写分离.分库分表). 处理方向:明确优化目标.性能和安全的折中.防患未 ...

  2. 中秋节,送上一次非常有趣的SQL优化实战经历

    点击上方"搜云库技术团队",选择"设为星标" 回复"1024"或"面试题"获取4T学习资料 补充:看到好多朋友后台留言说 ...

  3. MySQL进阶SQL优化

    MySQL进阶SQL优化 查询效率分析: 子查询为确保消除重复值,必须为外部查询的每个结果都处理嵌套查询.在这种情况下可以考虑用联接查询来取代. 如果要用子查询,那就用EXISTS替代IN.用NOT ...

  4. [转]Mysql中的SQL优化与执行计划

    From : http://religiose.iteye.com/blog/1685537 一,如何判断SQL的执行效率? 通过explain 关键字分析效率低的SQL执行计划. 比如: expla ...

  5. MySQL优化篇:SQL优化流程

    MySQL中SQL优化流程 SQL优化流程如下: 慢查询的开启并捕获 explain+慢SQL分析 show profile查询SQL在MySQL服务器里面的执行细节和生命周期情况 SQL数据库服务器 ...

  6. 5大步骤+10个案例,堪称SQL优化万能公式

    作者丨狼爷 来源丨网址:https://www.cnblogs.com/powercto/p/14410128.html 一.前言 在应用开发的早期,数据量少,开发人员开发功能时更重视功能上的实现,随 ...

  7. 15 种 SQL 优化中,老司机才懂的处理技巧

    前言 SQL优化是一个大家都比较关注的热门话题,无论你在面试,还是工作中,都很有可能会遇到. 如果某天你负责的某个线上接口,出现了性能问题,需要做优化.那么你首先想到的很有可能是优化SQL语句,因为它 ...

  8. 面试官:不会看 Explain执行计划,简历敢写 SQL 优化?

    来自:程序员内点事 昨天中午在食堂,和部门的技术大牛们坐在一桌吃饭,作为一个卑微技术渣仔默默的吃着饭,听大佬们高谈阔论,研究各种高端技术,我TM也想说话可实在插不上嘴. 聊着聊着突然说到他上午面试了一 ...

  9. 大牛是怎么思考设计SQL优化方案的?

    作者:惨绿少年 https://www.cnblogs.com/clsn/p/8214048.html 在进行MySQL的优化之前,必须要了解的就是MySQL的查询过程,很多查询优化工作实际上就是遵循 ...

  10. MySQL · 性能优化· CloudDBA SQL优化建议之统计信息获取

    阿里云CloudDBA具有SQL优化建议功能,包括SQL重写建议和索引建议.SQL索引建议是帮助数据库优化器创造最佳执行路径,需要遵循数据库优化器的一系列规则来实现.CloudDBA需要首先计算表统计 ...

最新文章

  1. ogre3d环境配置与简单程序示例
  2. 前端开发我为什么选择cordova
  3. java课程设计题目及代码中国象棋,写的太详细了
  4. python最佳实践笔记
  5. 【超分辨率实验】Matlab-使用深度学习的单图像超分辨率(Single Image Super-Resolution Using Deep Learning)
  6. MySQL实战—更新过程
  7. python的一些库(模块)集合
  8. [JSOI2008]Blue Mary的战役地图
  9. edge 浏览器中数字显示为链接
  10. 根据sessionId获取Session对象
  11. ThickBox学习之一 ThickBox介绍以及单图片显示示例
  12. 嵌入式系统Linux内核开发学习指导框图
  13. 有效IT运维 效率提高 成本降低
  14. iOS开发最新之CocoaPods环境配置教程
  15. php标准代码格式,PHP PSR代码格式规范
  16. acs880变频器选型手册_设备安装:变频器调试成功就差这一步了
  17. stm32最小原理图的PCB图绘制(含AHT20温度传感器)
  18. 集成电路制造工艺及设备
  19. mp3排序软件哪个好用_电脑上有什么录音软件,哪个电脑录音软件好用
  20. Centos7安装Docker后无法启动:Failed to program NAT chain: INVALID_ZONE: docker

热门文章

  1. Android Studio 2.0来啦
  2. python基础之迭代器、生成器、装饰器
  3. 2019夏软工暑期随笔3
  4. 文本编辑器Vim/Neovim任意代码执行漏洞(CVE-2019-12735)
  5. 【Linux】解决Wesnoth中文乱码问题
  6. develop note 1
  7. 子级Repeater获取 父级Repeater 中的值
  8. 响应activex事件
  9. pytorch使用说明2
  10. JSON文件导入Unity3d中是空的的问题