sql优化常用的几种方法:19种最有效的sql优化技巧-程序员宅基地

技术标签: java  mysql  数据库  sql  

我们来谈谈项目中常用的MySQL优化方法,共19条,具体如下:

1、EXPLAIN

做MySQL优化,我们要善用EXPLAIN查看SQL执行计划。

下面来个简单的示例,标注(1、2、3、4、5)我们要重点关注的数据:

MySQL对于IN做了相应的优化,即将IN中的常量全部存储在一个数组里面,而且这个数组是排好序的。但是如果数值较多,产生的消耗也是比较大的。再例如:select id from t where num in(1,2,3) 对于连续的数值,能用between就不要用in了;再或者使用连接来替换。

3、SELECT语句务必指明字段名称

SELECT*增加很多不必要的消耗(CPU、IO、内存、网络带宽);增加了使用覆盖索引的可能性;当表结构发生改变时,前断也需要更新。所以要求直接在select后面接上字段名。

4、当只需要一条数据的时候,使用limit 1

这是为了使EXPLAIN中type列达到const类型

5、如果排序字段没有用到索引,就尽量少排序6、如果限制条件中其他字段没有索引,尽量少用or

or两边的字段中,如果有一个不是索引字段,而其他条件也不是索引字段,会造成该查询不走索引的情况。很多时候使用union all或者是union(必要的时候)的方式来代替“or”会得到更好的效果。

7、尽量用union all代替union

union和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。当然,union all的前提条件是两个结果集没有重复数据。

8、不使用ORDER BY RAND()

select id from `dynamic` order by rand() limit 1000;

上面的SQL语句,可优化为:

select id from `dynamic` t1 join (select rand() * (select max(id) from `dynamic`) as nid) t2 on t1.id > t2.nidlimit 1000;

9、区分in和exists、not in和not exists

select * from 表A where id in (select id from 表B)

上面SQL语句相当于

select * from 表A where exists(select * from 表B where 表B.id=表A.id)

区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询。所以IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

关于not in和not exists,推荐使用not exists,不仅仅是效率问题,not in可能存在逻辑问题。如何高效的写出一个替代not exists的SQL语句?

原SQL语句:

select colname … from A表 where a.id not in (select b.id from B表)

高效的SQL语句:

select colname … from A表 Left join B表 on where a.id = b.id where b.id is null

取出的结果集如下图表示,A表不在B表中的数据:

select id,name from product limit 866613, 20

使用上述SQL语句做分页的时候,可能有人会发现,随着表数据量的增加,直接使用limit分页查询会越来越慢。

优化的方法如下:可以取前一页的最大行数的id,然后根据这个最大的id来限制下一页的起点。比如此列中,上一页最大的id是866612。SQL可以采用如下的写法:

select id,name from product where id> 866612 limit 20

11、分段查询

在一些用户选择页面中,可能一些用户选择的时间范围过大,造成查询缓慢。主要的原因是扫描行数过多。这个时候可以通过程序,分段进行查询,循环遍历,将结果合并处理进行展示。

如下图这个SQL语句,扫描的行数成百万级以上的时候就可以使用分段查询:

对于null的判断会导致引擎放弃使用索引而进行全表扫描。

13、不建议使用%前缀模糊查询

例如LIKE“%name”或者LIKE“%name%”,这种查询会导致索引失效而进行全表扫描。但是可以使用LIKE “name%”。

那如何查询%name%?

如下图所示,虽然给secret字段添加了索引,但在explain结果并没有使用:

那么如何解决这个问题呢,答案:使用全文索引。

在我们查询中经常会用到select id,fnum,fdst from dynamic_201606 where user_name like %zhangsan%; 。这样的语句,普通索引是无法满足查询需求的。庆幸的是在MySQL中,有全文索引来帮助我们。

创建全文索引的SQL语法是:

ALTER TABLE `dynamic_201606` ADD FULLTEXT INDEX `idx_user_name` (`user_name`);

使用全文索引的SQL语句是:

select id,fnum,fdst from dynamic_201606 where match(user_name) against(zhangsan in boolean mode);

注意:在需要创建全文索引之前,请联系DBA确定能否创建。同时需要注意的是查询语句的写法与普通索引的区别。

14、避免在where子句中对字段进行表达式操作

比如:

select user_id,user_project from user_base where age*2=36;

中对字段就行了算术运算,这会造成引擎放弃使用索引,建议改成:

select user_id,user_project from user_base where age=36/2;

15、避免隐式类型转换

where子句中出现column字段的类型和传入的参数类型不一致的时候发生的类型转换,建议先确定where中的参数类型。

16、对于联合索引来说,要遵守最左前缀法则

举列来说索引含有字段id、name、school,可以直接用id字段,也可以id、name这样的顺序,但是name;school都无法使用这个索引。所以在创建联合索引的时候一定要注意索引字段顺序,常用的查询字段放在最前面。

17、必要时可以使用force index来强制查询走某个索引

有的时候MySQL优化器采取它认为合适的索引来检索SQL语句,但是可能它所采用的索引并不是我们想要的。这时就可以采用forceindex来强制优化器使用我们制定的索引。

18、注意范围查询语句

对于联合索引来说,如果存在范围查询,比如between、>、<等条件时,会造成后面的索引字段失效。

19、关于JOIN优化

LEFT JOIN A表为驱动表,INNER JOIN MySQL会自动找出那个数据少的表作用驱动表,RIGHT JOIN B表为驱动表。

注意:

1)MySQL中没有full join,可以用以下方式来解决:

select * from A left join B on B.name = A.namewhere B.name is nullunion allselect * from B;

2)尽量使用inner join,避免left join:

参与联合查询的表至少为2张表,一般都存在大小之分。如果连接方式是inner join,在没有其他过滤条件的情况下MySQL会自动选择小表作为驱动表,但是left join在驱动表的选择上遵循的是左边驱动右边的原则,即left join左边的表名为驱动表。

3)合理利用索引:

被驱动表的索引字段作为on的限制字段。

4)利用小表去驱动大表:

从原理图能够直观的看出如果能够减少驱动表的话,减少嵌套循环中的循环次数,以减少 IO总量及CPU运算的次数。

5)巧用STRAIGHT_JOIN:

inner join是由MySQL选择驱动表,但是有些特殊情况需要选择另个表作为驱动表,比如有group by、order by等「Using filesort」、「Using temporary」时。STRAIGHT_JOIN来强制连接顺序,在STRAIGHT_JOIN左边的表名就是驱动表,右边则是被驱动表。在使用STRAIGHT_JOIN有个前提条件是该查询是内连接,也就是inner join。其他链接不推荐使用STRAIGHT_JOIN,否则可能造成查询结果不准确。

这个方式有时能减少3倍的时间。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Lost_in_the_woods/article/details/125659716

智能推荐

更便捷更高效地生产影像地图瓦片_瓦片数据库生产-程序员宅基地

文章浏览阅读1k次。针对海量影像地图,采用地理处理建模构建切片业务流程,并应用“基于金字塔算法生成瓦片”的方案实施更高效的影像地图瓦片生产。_瓦片数据库生产

00942 ora 表存在_"ORA-00942: 表或视图不存在" 的原因和解决方法-程序员宅基地

文章浏览阅读1.3w次。1、问题产生的原因Oracle 是大小写敏感的,我们创自己写Sql脚本创建表的时候Oracle会自动将我们的表名,字段名转成大写。2、问题分析但是 Oracle 同样支持"" 语法,将表名或字段名加上""后,Oracle不会将其转换成大写。如果加上了"",那么我们采用一般的SQL语句查询则会产生“ORA-00942: 表或视图不存在 ”,因此SQL脚本中需要将表名也加上""。例如:select*..._ora00942表或视图不存在,但明明存在

ES2007的tomcat报错的原因_tomcat报错esservicecontraller-程序员宅基地

文章浏览阅读392次。方正ES2007,在能成功连接数据库的前提下,如果tomcat报错,那么你就可以看看你的ip地址是否仍然是自动获取ip,如果是请更改过来,使用具体的ip地址(类似192.168.1.11....),再跑一遍就Ok了。_tomcat报错esservicecontraller

es修改排序_java 如何实现ElasticSearch自定义排序-程序员宅基地

文章浏览阅读1k次。1、es版本用的是5.1由于需要使用es的script的inline功能,需要修改es yml的配置文件,增加如下配置使其支持inlinescript.inline: onscript.stored: onscript.file: onscript.engine.groovy.inline.aggs: on增加完成上述配置需要重启es 注:不同的es版本配置不同2、java代码# 定义传入scri..._es addsort

计算机主机故障有哪些,电脑硬件常见故障有哪些-程序员宅基地

文章浏览阅读1.7k次。电脑硬件常见故障有哪些计算机硬件是指计算机系统中由电子,机械和光电元件等组成的各种物理装置的总称。下面小编来给大家介绍电脑硬件常见故障,希望对大家有帮助!1、CPU温度是CPU常见的'一个问题,CPU温度过高的时候会出现电脑频繁重启的现象,而且是每次开机还未进入系统就重启了,每次重启的时间也越来越短,这个时候就很有可能是CPU温度过高。2、主板电脑有时候开机屏幕上什么也不显示,并且没有出现报错声时..._电脑主机故障的八种表现和对应的现象是什么

java 之 静态泛型方法_java static 泛型 方法-程序员宅基地

文章浏览阅读585次。java 之 静态泛型方法_java static 泛型 方法

随便推点

IJPay支付开源 让你的代码飞起来_ijpay 如何运行-程序员宅基地

文章浏览阅读631次。今天我要给大家推荐一个非常棒的支付开源项目,最近大家在不忙的时候可以学习一下,项目在GitHub有3.3k ,GITEE已有6.5k之多~特别说明:不依赖任何第三方 MVC 框架,仅仅作为工具使用简单快速完成支付模块的开发,可轻松嵌入到任何系统里。微信支付支持多商户多应用,普通商户模式与服务商商模式当然也支持境外商户、同时支持 Api-v3 与 Api-v2 版本的接口。支付宝支付支持多商户多应用,签名同时支持普通公钥方式与公钥证书方式目前封装好的SDK仅支持安卓 ,IOS还在开发中~~~~IJP_ijpay 如何运行

Vue 使用 Apache Echarts 绘制地图(省市、地区、自定义)_vue 地图-程序员宅基地

文章浏览阅读2.3w次,点赞77次,收藏260次。使用Apache Echarts绘制中国、省市级、自定义地图的方法_vue 地图

软件开发工具【十四】 之 常用建模工具_建模工具开发学习-程序员宅基地

文章浏览阅读5.4k次,点赞4次,收藏11次。感谢内容提供者:金牛区吴迪软件开发工作室接上一篇:软件开发工具【十三】 之 Eclipse插件的使用与开发文章目录一、UML建模介绍1.面向对象方法的出现和发展2.面向对象的一些概念3.面向对象方法的基本过程4.组件思想二、RATIONAL ROSE建模工具介绍1.RATIONAL 公司简介2.面向对象的分析设计和Rational Rose3.Rational Rose可视化建模的特点三、使用RATIONAL ROSE 建模1.UML建模的三大部分2.需求分析之用例图与活动图3.系统分析与设计四、E._建模工具开发学习

如何通过gdb查看反汇编代码_pwngdb 显示汇编代码-程序员宅基地

文章浏览阅读2.4w次,点赞15次,收藏77次。0x00 程序源码C代码如下:#include &amp;lt;stdio.h&amp;gt;int addme(int a, int b){ int c ; c = a+ b; return c;}int main(int argc, char const *argv[]){ int ret= 0; ret = addme(10,20); pri..._pwngdb 显示汇编代码

View的简介_view在编程中什么意思-程序员宅基地

文章浏览阅读1.6w次,点赞17次,收藏34次。认识一个新的事物,首先我们从概念上讲,我们需要知道,这个事物 是什么,这个事物有什么用途?对应到View 上,我们要搞明白 View 的定义以及工作原理。 1.View是什么? View是屏幕上的一块矩形区域,它负责用来显示一个区域,并且响应这个区域内的事件。可以说,手机屏幕上的任意一部分看的见得地方都是View,它很常见,比如 TextView 、ImageView 、Button_view在编程中什么意思

ES 内存使用和GC指标_es gc count多少算异常-程序员宅基地

文章浏览阅读3k次。摘录自:http://blog.csdn.net/yangwenbo214/article/details/74000458ES 内存使用和GC指标——主节点每30秒会去检查其他节点的状态,如果任何节点的垃圾回收时间超过30秒(Garbage collection duration),则会导致主节点任务该节点脱离集群。内存使用和GC指标在运行Elasticsearch时,内存是您..._es gc count多少算异常

推荐文章

热门文章

相关标签