设为首页 收藏本站
查看: 869|回复: 0

[经验分享] 高性能MySql进化论(十一):常见查询语句的优化

[复制链接]

尚未签到

发表于 2016-10-22 09:54:25 | 显示全部楼层 |阅读模式
  总结一下常见查询语句的优化方式

1COUNT
  1. COUNT的作用
  ·COUNT(table.filed)统计的该字段非空值的记录行数
  ·COUNT(*)或者是COUNT(not nullable field) 统计的是全表的行数
  如果要是统计全表记录数,COUNT(*)效率会比COUNT(not nullable field)要高一点
  2. MYISAM的COUNT
  一般执行COUNT操作时需要扫描大量的记录,但是在MyISAM引擎的数据库中,数据库把表的记录数保存起来,所以COUN(*)会非常的快(前提是不包含where条件)
  3. 当需要频繁的使用COUNT时,可以考虑使用汇总表的策略
  4. 优化小例子

在MYISAM中进行范围查询时,可以减少检索行数的小技巧

原始的:select count(*) from dictionary where id>5.

  优化后:select (select count(*) fromdictionary)-count(*) from dictionary where id<=5
  
  减少查询次数
  优化前:需要两条语句
   Select count(*)from student where area=’SH’
   Select count(*)from student where area=’BJ’
  优化后:合并成一条
  select count(area='SH') as shcount, count(area='BJ') as bjcount from student;


2优化关联查询
  1. 确保ON或USING的字句上有索引
  2. 一般情况下只需要在第二个表上创建索引
  3. 尽量使 Group by/Order by的表达式中只包含一个表的字段
  

3优化子查询
  尽量用关联代替子查询

4优化Group by 以及Distinct
  1. 当对关联查询执行group by操作时,使用查询表的标识列作为分组条件效率会比较高
  2. 当需要查询的非group by指定的字段时,正常情况下是无法执行的,可以通过inner join 的形式来弥补

select firstname, lastname
from actor
inner join(select  actor_id, count(*) as cnt from actor group by(actor_id))
using (actor_id)
  3. group by默认会对查询的结果进行排序,数据量很大的时候可能会比较耗资源,如果你不关心查询结果的顺序,可以通过order by null 避免这种不必要的浪费
  

5LIMIT分页
  在进行分页查询的时候往往是采用select * from table1 limit 100,20 的方式来提取数据,在处理的过程中会读取120条数据,然后扔掉100条的offset记录,最后返回20条记录给客户端。如果offset的值非常大,效率上可能会有影响,可以尝试
  1. 可以通过覆盖索引+inner join的方式来重写sql
  

select field1,field2,field3
from table1
inner join
(select id from table1 limit 100, 20) as temp
using(id)


  2. 如果可以计算出明确的开始点和结束点,可以转换成 between and 的方式,这种方式只会扫描指定的行数,效率比较高
  Select * from table1 between 100 and 120.
  
  3. 可以通过位置标签的方式,来减少需要检索的记录数
  例如 从某个位置开始。 Select * from table1 whereid>100 limit 20
  
  下图列出了三种方式的效率对比
   DSC0000.jpg
  在进行分页处理的时候往往需要知道记录的总数,然后用这些总数生成页码。获取总数往往是使用count或是伴随一次全表查询得到的,这个过程也是检索所有的记录,然后再丢掉。为了避免这种浪费可以采取两种策略
  ·把页码换成“下一页”的方式,这样就只需要去取固定的条数
  ·一次性读取1000条,当一千条使用完后,采用“获取更多记录”的方式再获取1000条
  
  

6UNION
  ·使用的时候要把每个优化手段下推到每个子集中(http://blog.csdn.net/eric_sunah/article/details/17290641)
  ·Union操作会对处理后的结果执行distinct操作,这在很多时候是没有必要的。可以采用union all来避免这个问题
  
  

7自定义变量
  合理灵活的使用自定义变量往往会给程序的性能带来意想不到的效果,但往往也会带来与其他数据库系统的兼容性问题。
  下面列出几个自定义变量使用的小例子
  ·行号
  mysql> set @rownumber:=0;
  mysql> select mean, @rownumber:=@rownumber+1 from dictionary limit10;
  
  ·避免重复查询刚刚更新的数据
  在更新完一条记录后,往往需要再次执行select查询刚刚更新过的记录
  通过变量可以避免这种问题
  Mysql>set @updaterow:=null;
  mysql> update dictionary set mean='update get variable' where id=100and @updaterow:=now();
  
  ·统计更新和插入的数量
  mysql> set @x:=0; //define avariable
  mysql> insert into dictionary (id,mean) values(3,'duplicate') onduplicate key update mean=values(mean)+(0*(@x:=@x+1)); //insert a duplicaterecord
  mysql> select @x; //get x value, it’s indicator duplicate times
  

8静态分析工具
  有时候可以借助专门的查询分析工具来发现自己的问题,比如pt-query-advisor(http://www.percona.com/doc/percona-toolkit/2.1/pt-query-advisor.html)
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-289726-1-1.html 上篇帖子: Mysql ibdata 丢失或损坏如何通过frm&ibd 恢复数据 下篇帖子: 高性能MySql进化论(八):表以及索引的维护
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表