其实,在写这篇博客之前,我也是感觉自己会点优化,至少知道不要使用“*”号啊,给经常查询的列创建索引啊什么的,其实都不是大家想的那样简单的,其实它们背后存在很多的东西,值得我们去理解和学习。
和大家分享讨论一个问题吧,子查询和连接查询哪一个查询速度快?最重要的目的是能帮助大家在以后的开发路上不要再犯我这种的错误,看到就是赚到,哈哈。
我的答案是连接查询。因为这是我在前几天的实践项目中亲身体会到的,感触颇深,在给我们公司的网站首页执行了一条统计SQL语句,当时我是用子查询写的sql语句,第一次执行了21.783sec,第二次执行了5.178sec,当时感觉很别扭,一个网站的首页加载要经过3-4秒钟才能刷出统计数据,太离谱了,于是我就尝试用连接查询进行改造一下,果然,查询速度嗖一下上去了,当时感觉有种征服了什么东西一样,真的,超有成就感,以前确实是写代码,没在这方面过多留意过,这次钻了一次确实挺好。
直接上图吧,给大家展示一下子查询和连接查询的执行时间,(但是,一条sql语句的性能不能光靠查询时间来衡量,之前在一篇博文里看到的,蛮有感觉的)
一、子查询统计
执行了5.198sec
二、连接查询统计
执行了0.010sec。
(为什么连接查询比子查询块,这个问题我一直在总结,比较它们的查询原理是如何扫描表结构的,一致还没能总结出一个舒服的答案,等后期总结好了分享,更希望高手指点,希望高手留言相助,正在努力理解...)
好了,跟大家分享一点小东西之后,我们就切入正题,来谈谈简单优化及它们是如何来提升性能的。
1、MySQL的查询过程:当我们通过MySQL的客户端发送一条SQL语句时,MySQL服务器到底做了哪些动作,经历了哪些过程,我还是借图说明吧
简单给大家说明一下吧。
MySQL数据库也是客户端/服务端通信协议的模式,在任意时刻,无非就是要么客户端向服务端发送请求,要么服务端向客户端响应查询结果,这两个动作不能同时发生。一旦一端开始发送消息,另一端要接收完整个消息才能响应它,所以我们无法将一个请求消息切成小块独立发送,也没有办法进行流量控制。
当客户端向服务端发送sql语句时,首先客户端会把查询语句做成一个单独的数据包发送给服务端,这时如果查询语句很长则需要设置参数,如果实在太大,服务端可能会拒绝接受更多数据并抛出异常。
同理,与之相反的是服务端从存储引擎中拿到数据后响应给客户端,这时服务端响应的数据可能会很多,无法将这些数据做成一个数据包,可能会做成多个数据包。但是当服务器响应客户端请求时,客户端必须完整的接收整个返回结果,而不能简单的只取前面几条结果,然后让服务器停止发送。因而在实际开发中,尽量保持查询简单且只返回必需的数据,减小通信间数据包的大小和数量是一个非常好的习惯,这也是查询中尽量避免使用SELECT *以及加上LIMIT限制的原因之一。
2、查询时尽量使用limit做限制查询,原因上面已经分析,服务端可能会响应大量的数据包给客户端,我们通常只拿到前几条数据,后面的数据如果需要,则可以使用分页查询,边用边查。
3、还有一个误区就是,当我们在设计表结构时,尽量将字段的数据类型设置到最小,够用就行,别瞻前顾后,就拿int类型来说吧,我们习惯将给int类型的字段设置长度,其实吧,你设置不设置都没什么卵用,int类型是采用16位存储空间,那么它的存储范围就已经确定,所以int(1)和int(20)对于存储和计算是相同的,大家改改吧,我也是刚学到的。
4、我们在查询数据库,可能会用多个范围条件来作限制,比如查询某一时间段内入职的某一年龄段的员工,此时需要接纳的一点是,MySQL无法同时使用俩个字段的索引,它只会选择一种的一个字段的索引来做查询。
5、建议大家经常把表中一些不常用的索引删掉,定期删除一些长时间未使用过的索引是一个非常好的习惯。(在这儿给大家嘱咐一下,不要认为索引就是查询最好的工具,如果有时候查询非常小的表时,建议不要建立索引,直接全表扫描效果会更好)。
【
优化的学习旅程才刚开始,后期会给大家带来更多的经验,非常希望大家能够看到并给出建议。
参考博文:
http://www.cnblogs.com/zishengY/p/6892345.html,http://blog.csdn.net/luckarecs/article/details/7165472
】