SQL优化的方法_sql优化常用的几种方法-程序员宅基地

技术标签: 数据库  sql  

(1)建立物化视图或尽可能减少多表查询。

(2)以不相干子查询替代相干子查询。

(3)只检索需要的列。

(4)用带in的条件子句等价替换or子句。

(5)经常提交commit,以尽早释放锁。

(6)避免嵌套的游标(Cursor)和多重循环等。

(7)在经常查询的列上创建索引,提高查询效率。

(8)避免使用模糊查询进行匹配,如果一定要使用,建议使用最左模糊匹配原则。

(9)慢的查询的sql,根据性能和存储容量大小进行评估,适当的可以考虑水平分表和垂直分表,以提高sql的查询性能。

(10)查询数据是否存在,适当的可以使用exists替代in。

建表

1.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连 接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

2.尽可能的使用 varchar 代替 char ,因为首先变长字段存储空间小,可以节省存储空间, 其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

临时表

  1. 避免频繁创建和删除临时表,以减少系统表资源的消耗
  2. 尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
  3. 临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
  4. 在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log,以提高速度;
  5. 如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
  6. 如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table,然后 drop table,这样可以避免系统表的较长时间锁定。

游标的问题

  1. 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。游标的一个常见用途就是保存查询结果,以便以后使用。游标的结果集是由SELECT语句产生,如果处理过程需要重复使用一个记录集,那么创建一次游标而重复使用若干次,比重复查询数据库要快的多。
  2. 使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
  3. 与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。

事务

尽量避免大事务操作,提高系统并发能力。

数据量问题

13.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

具体SQL优化 

1.避免使用select *

select *不走覆盖索引,会有大量的回表操作,从而导致查询SQL的性能很低。应该使用具体的字段代替*,只返回使用到的字段。     

2.用union all代替union

union可以获取排除重复后的数据,union all可以获取所有数据,包含重复的数据,排除重复的过程需要遍历,排序和比较,他更耗时,更消耗CPU资源,所以如果能用union all,尽量不用union,除非是业务场景中不允许产生重复数据

3.小表驱动大表

in 和 not in 也要慎用,否则会导致全表扫描。对于连续的数值,能用 between 就不要用 in,对于子查询,可以用exists代替。

用小表的数据集驱动大表的数据集

in关键字,他会优先执行in里面的子查询语句,然后在执行in外面的语句,in里面的数据量很少,作为条件查询速度更快

exists关键字,他会优先执行exists左边的语句(即主查询语句),然后把它作为条件,去跟右边的语句匹配,如果匹配上,则可以查出数据,如果匹配不上,数据就被过滤掉了

in适用于左边大表,右边小表

exists适用于左边小表,右边大表

4.批量操作

每次远程请求数据库,是会消耗一定性能的

提供一个批量插入的方法,这样只需要远程请求一次数据库,SQL性能会提升,数据量越大,提升越多,但是不建议一次批量操作太多数据,如果数据太多,数据库响应也会很慢,批量操作需要把握一个度,建议每批数据尽量控制在500以内,多批如果数据多于500,则分多批处理。

5.多用limit

6.in中值太多

如果in数据太多,不做任何限制,可能会导致接口超时

可以在SQL语句中对数据用limit做限制,不过更多的是在业务代码中加限制

如果超出500,可以分批用多线程去查询数据,每批只查500条记录,最后把查询到的数据汇总到一起返回

7.增量查询

有时候,我们需要通过远程接口查询数据,然后同步到另一个数据库,如果直接获取所有的数据,然后同步过去,这样如果数据很多,查询性能会非常差,可以按时间和id升序,每次只同步一批数据,这一批数据只有100条记录,每次同步完后,保存这100条数据中最大的id和时间,给同步下一批数据的时候用,通过这种增量查询的方式,能够提升单次查询的效率

select * from user where id > #{lastId} and create_time >= #{lastCreateTime} limit 100;

8.高效的分页

列表页在查询数据的时候,为了避免一次性返回过多的数据影响接口性能,我们一般会对查询接口做分页处理,在数据库中分页一般用的limit关键字如图

select id,name,age from user limit 10,20;

如果表中的数据量较少,用limit关键字做分页,没什么问题,但如果表中数据量很多,用他就会出现性能问题,

select id,name,age from user limit 1000000,20;

优化

select id,name,age from user where id >1000000 limit 20;

利用id上的索引查询,要求id是连续的,并且是有序的,还可以使用between优化分页

select id,name,age from user where id between 1000000 and  1000020;

between要在唯一索引上分页,不然会出现每页大小不一致的问题

9.用连接查询代替子查询

数据库中如果需要从两张以上的表中查询出数据的话,一般有两种方式,子查询和连接查询

子查询,可以通过in关键字实现,一个查询语句的条件落在另一个select语句的查询结果中,程序先运行嵌套在最内层的语句,在运行外层的语句,子查询的优点是简单,结构化,如果涉及的表数据不多的话,但缺点是数据库执行子查询时,需要创建临时表,查询完毕后,会删除这些临时表,有一些额外的性能消耗

select * from order where user_id in (select id from user where status=1);

连接查询,性能会更高

select o.* from order o
inner join user u on o.user_id=u.id
where u.status=1;

10.join的表不宜过多

join表的数据不应超过3个,如果join太多,数据库在选择索引的时候会非常复杂,很容易选错索引,并且如果每天命中,nested loop join就是分别从两个表读一行数据进行两两对比

11.join时要注意

我们在使用多张表联合查询的时候,一般会使用join关键字,join使用最多的是是left join和inner join

left join求两个表的交集外加左表剩下的数据

inner join求两个表交集的数据

12.索引

        并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。

        索引问题 法则:不要在建立的索引的数据列上进行下列操作:避免对索引字段进行计算操作。避免在索引字段上使用not,<>,!=。避免在索引列上使用IS NULL和IS NOT NULL。避免在索引列上出现数据类型转换。避免在索引字段上使用函数。避免建立索引的列中使用空值。

        索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率 因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要

        在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

控制索引的数量:索引可以显著提升 查询的性能,但索引数量并非越多越好,因为表中新增数据时,需要同时为他创建索引,而索引时需要额外的存储空间的,而且还会有一定的性能消耗,单表中的索引数量应该尽量控制在5个以内,并且单个索引中的字段不超过5个

13.合理的数据类型

14.提升group by的效率

select user_id,user_name from order group by user_id having user_id <=200;

优化

select user_id,user_name from order where user_id <=200 group by user_id;

15,索引优化

检查SQL语句有没有走索引-explain查看数据库的执行计划

 

16.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

where 表之间的连接必须写在其他 Where 条件之前, 那些可以过滤掉最大数量记录的条件必须写在 Where 子句的末尾,HAVING 最后。

不要在where条件中使用左右两边都是%的like模糊查询,这样会导致数据库引擎放弃索引进行全表扫描。优化:尽量在字段后面使用模糊查询

尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,优化:可以用in代替or。

尽量不要在 where 子句中对字段进行表达式操作,这样也会造成全表扫描。

where条件里尽量不要进行null值的判断,null的判断也会造成全表扫描。给字段添加默认值,对默认值进行判断。

尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描

应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。将表达式.函数操作移动到等号右侧。

不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引

尽量不要使用where 1=1的条件,有时候,在开发过程中,为了方便拼装查询条件,我们会加上该条件,这样,会造成进行全表扫描。优化:如果用代码拼装sql,则由代码进行判断,没where加where,有where加and如果用mybatis,请用mybatis的where语法。

其他的优化

20.Update 语句,如果只更改1、2个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志。

21.尽量使用Join 语句来替代子查询,因为子查询是嵌套查询,而嵌套查询会新创建一张临时表,而临时表的创建与销毁会占用一定的系统资源以及花费一定的时间,同时对于返回结果集比较大的子查询,其对查询性能的影响更大

22.对于多张大数据量(这里几百条就算大了)的表JOIN,要先分页再JOIN,否则逻辑读会
很高,性能很差。

23.前提也是在sql基础优化完成后,有多表联合查询导致查询数据很慢,可以在代码上进行分割,如一条语句查多个表,可以拆分成两条sql语句或者多条sql语句,然后再代码上进行数据拼装。

24.业务层面优化是指在sql基础优化上没有问题之后,然后一次性查询的数据量很大,达到上亿的数据量,即使是分页也会很慢,所以要在业务层面进行优化,固定条件,缓存count值,避免每次查询全表扫描计算count值,每次更新都要对count值进行同步修改

Count优化

count(column) :是表示结果集中有多少个column字段不为空的记录。

count(*) :是表示整个结果集有多少条记录

count(1):InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。count(1) 执行得要比 count(主键 id) 快。因为从引擎返回 id 会涉及到解析数据行,以及拷贝字段值的操作。

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

智能推荐

学习资料要去哪里打印,网上打印靠谱吗?_去哪里打印学习资料-程序员宅基地

文章浏览阅读218次。很多人喜欢将对自己有用的学习资料整理下来,资料整理好以后打印出来可以更好的查看,倘若仅有一两张资料需要打印的话,大家可以随便找一家打印店即可,价格方面即便是稍微贵一点也不会差别特别大。但倘若学习资料如果份数比较多,比如有上百张、上千张资料需要打印,这时候大家就需要找一些打印价格相对比较便宜,比较正规的打印平台进行打印,小编推荐大家打印学习资料可到专业的网上在线打印平台易桌面打印室提交文件资料进行打印。易桌面打印室是一个比较专业的网上在线打印平台,该平台可快速为大家打印各种类型的资料、试卷、书本等,在打印资_去哪里打印学习资料

微信小程序 淘宝_淘宝微信小程序-程序员宅基地

文章浏览阅读4.8k次,点赞2次,收藏33次。模仿淘宝写了一个小程序,主要目的还是练手并且以页面效果为主,写法肯定也会有更好的,后续继续加强。登录页面的话,就直接点登录进入到首页了,没有做过多的交互。其中做比较多的交互是购物车,应数据的形式做出的交互,实际的项目中可能会有更好的数据形式,产品数增减全选合计等,事件传参比较多;下面以购物车为例,贴上购物车的部分js 代码,里面有个“监听”是否勾选和计数的函数(watchSelec..._淘宝微信小程序

并发计算模型BSP与SEDA_bulk synchronous parallel-程序员宅基地

文章浏览阅读3.6k次。1 BSP批量同步并行计算BSP(Bulk Synchronous Parallel)批量同步并行计算用来解决并发编程难的问题。名字听起来有点矛盾,又是同步又是并行的。因为计算被分组成一个个超步(super-step),超步内并行计算并且结点间不能通信。在超步之间设置同步栅栏(barrier synchronization),计算完成后相互通信,全部完成后才能继续下一个超步。2 SEDA阶段_bulk synchronous parallel

企业微信的后台怎么进入和管理?_企业微信后台-程序员宅基地

文章浏览阅读1w次。企业微信的后台怎么进入和管理? _企业微信后台

【机器学习】QQ-plot深入理解与实现_python qqplot subplot-程序员宅基地

文章浏览阅读1.2w次。QQ-plot深入理解与实现26JUNJune 26, 2013最近在看关于CSI(Channel State Information)相关的论文,发现论文中用到了QQ-plot。Sigh!我承认我是第一次见到这个名词,异常陌生。维基百科给出了如下定义:“在统计学中,QQ-plot(Q代表分位数Quantile)是一种通过画出分位数来比较两个概率分布的图形方法。首先选定_python qqplot subplot

mybatis设置sql执行时间超时时间_mybatis timeout-程序员宅基地

文章浏览阅读2.8w次,点赞3次,收藏21次。存在这样的场景,当一些比较耗时的查询时,如果不中断,则会导致数据库堵塞,进而会拖垮整个数据库服务的正常运行。1.如果你使用的是HikariCP连接池的话,可以在配置文件设置connetion-timeout这个属性(如application.properties)2.如果你使用的是其他链接池,比如tomcat连接池,同时持久化框架用的是mybatis的话,那可以这样设置2.1 在配置文..._mybatis timeout

随便推点

中断中处理延时及一些函数的调用规则(中断调i2c驱动有感)_模拟iic的延时对定时器中断的影响-程序员宅基地

文章浏览阅读4.5k次。转自:http://blog.csdn.net/xiyu_1986/article/details/69969271,中断处理程序中不能使用有睡眠功能的函数,如ioremap,kmalloc,msleep等,理由是中断程序并不是进程,没有进程的概念,因此就没有休眠的概念;2,中断处理程序中的延时可以用忙等待函数来代替,如ndelay,udelay,mdelay等,这些函数在实现上本质是根据_模拟iic的延时对定时器中断的影响

iphone12文件管理连接服务器,iPhone手机打开服务器功能,和Windows电脑互传文件方法...-程序员宅基地

文章浏览阅读5.2k次。iPhone手机打开服务器功能,和Windows电脑互传文件方法PC端设置:一、在计算机端新建一个文件夹,例如取名为:“iphone共享文件”。二、然后右键点击文件夹属,点击“共享”。三、打开共享后,再左键点击“共享”,下拉箭头选择“Everyone”然后继续选择“共享”,显示出共享文件夹的网络地址和共享文件夹的名字。PC端设置完成。Iphone手机端设置:一、选择iphone手机“文件”,点击右..._iphone 手机的连接服务器 怎么连接电脑

obb包围盒数组的含义_obb包络盒-程序员宅基地

文章浏览阅读257次。OBB包围盒通常用一个包含12个元素的数组来表示,这些元素描述了包围盒的位置、尺寸和旋转。总之,这个包含12个元素的数组描述了OBB包围盒的位置、旋转和尺寸信息。第二行这三个元素表示包围盒的旋转信息,通常以旋转矩阵的形式给出。第四行这三个元素表示包围盒每个轴上的半边长,通常是尺寸的一半。:旋转矩阵的第一行,通常是X轴的旋转分量。:旋转矩阵的第二行,通常是Y轴的旋转分量。:旋转矩阵的第三行,通常是Z轴的旋转分量。:包围盒的中心点在X轴上的坐标。:包围盒的中心点在Y轴上的坐标。:包围盒的中心点在Z轴上的坐标。_obb包络盒

明远智睿MY-IMX6-EK200 L3035测试手册(2)_imx6 五个串口-程序员宅基地

文章浏览阅读319次。【接上一章节明远智睿MY-IMX6-EK200 L3035测试手册(1)】2.7 串口测试MY-I.MX6评估板有5个串口,其中4个为用户串口(位于底板正面“J1”位置,丝印名称为“TTL_UART”),1个为调试串口(位于底板正面“P2”位置)。 测试说明系统设备文件说明:调试串口的在系统中的设备文件是ttymxc0,用户串口的设备文件是ttymxc1、ttymxc2、t..._imx6 五个串口

QT软件开发-基于FFMPEG设计视频播放器-GPU硬解、OpenGL渲染(四)_qt gpu渲染画面-程序员宅基地

文章浏览阅读1.3k次。前面几篇文章里分别介绍了ffmpeg软解、硬解、音频解码,完成视频帧渲染,音频解码播放。之前做的视频播放器里,虽然也使用了硬件加速解码,解码确实快,但是渲染都采用QWidget方式渲染绘制,占用CPU较高,并且采用QWidget方式渲染,需要将硬解码之后的数据转为RGB24,然后封装为QImage这个过程非常消耗时间,如果是高清4K视频整个视频解码播放就会非常卡顿,CPU占用直接100%。这篇文章将渲染方式换成OpenGL,解码方式还是采用硬件加速解码,充分利用GPU,降低CPU占用,提高整体视频播放效率。_qt gpu渲染画面

element 中手动上传文件_element手动上传-程序员宅基地

文章浏览阅读1.6k次。element手动上传文件_element手动上传