作为一名后端程序员,可以说天天都要跟数据库打交道,不管使用的是MySQL,Oracle还是SQLServer,毫无疑问都逃不开SQL,所以日常工作中对于SQL的性能优化可谓说十分重要。今天阿粉就带大家看一下,每个后端程序员都应该知道的十个提升查询性能的技巧。1、使用Exists代替子查询 子查询在日常的工作中不可避免一定会使用到,很多时候我们的用法都是这样的:SELECTId,NameFROMEmployeeWHEREDeptIdIn(SELECTIdFROMDepartmentWHERENamelikeManagement); 相信大家平常肯定都是这样来使用的,其实还有一种更好的方法,如下所示:SELECTId,NameFROMEmployeeWHEREDeptIdExist(SELECTIdFROMDepartmentWHERENamelikeManagement); 这里我们使用exist关键字而不是In关键字,当然如果在数据量不大的时候,两种方式都可以,但是当数据量很大的时候,exist的方式会比in的方式效率高很多。因为Exist函数根据查询结果返回一个布尔值,速度会快很多。2、适当的使用JOIN来代替子查询 除了上面的exist之外在有些场景我们可以使用JOIN来替换子查询,毕竟子查询的效果是很差的,如下所示:SELECTId,NameFROMEmployeeWHEREDeptIdin(SELECTIdFROMDepartmentWHERENamelikeManagement); 使用JOIN的方式如下:SELECTEmp。Id,Emp。Name,Dept。DeptNameFROMEmployeeEmpRIGHTJOINDepartmentDeptonEmp。DeptIdDept。IdWHEREDept。DeptNamelikeM3、使用Where替代不必要的Having 对于where的使用相信大家都很擅长,但是对于Having的使用可能平时用得不多,阿粉这里只能说:用得不多,挺好的!对于Having我们是能不用就不用不到万不得已的时候不要用,说真的阿粉工作这么多年,真没有使用Having的场景。我们先看下面的示例: Having的用法SELECTEmp。Id,Emp。Name,Dept。DeptName,Emp。SalaryFROMEmployeeEmpRIGHTJOINDepartmentDeptonEmp。DeptIdDept。IdGROUPBYdept。DeptNameHAVINGEmp。Salary20000; Where的用法SELECTEmp。Id,Emp。Name,Dept。DeptName,Emp。SalaryFROMEmployeeEmpRIGHTJOINDepartmentDeptonEmp。DeptIdDept。IdWHEREEmp。Salary20000; 为什么说Having的性能没有Where高呢?那是因为Where是一种精确的匹配,但是Having是需要配合GroupBy来配合使用,只要涉及到GroupBy自然就效率高不起来了。4、使用精确的字段类型 有些小伙伴为了系统的可扩展性或者压根就不知道该把数据库字段的类型设置什么,所以就全部使用char或者varchar,总觉得这样更灵活,但是往往这个时候是对系统的最大隐患。 在使用时间类型的字段的时候,就需要设置成DateTime,不能用在使用标识是否删除的时候就应该使用tinyint,能用varchar的就不要用对于大字段text需要独立出来,这样在查询的时候就不会影响性能;对于能设置成唯一键的就需要设置成唯一键,因为你永远无法避免程序会出现脏数据,要在数据层保证一致性。5、使用批处理代替循环 在插入数据的时候的,我们可以使用values来批量进行插入,而不是通过循环来进行单条数据的查询,如下所示:不可取For(Inti0;i5;i){INSERINTOTable1(Id,Value)Values(i,Valuei);}推荐INSERTINTOTable1(Id,Value)Values(1,Value1),(2,Value2),(2,Value3),(4,Value4),(5,Value5); 不过要注意values后面的数量也是有限制的,所以两者可以结合使用,具体的可以根据表字段的多少来决定分多少批来执行。另外这里有一个注意的点,很多系统都会底层做操作日志,而且很多时候可能是SQL级别的,那这个时候就需要注意,记录操作日志的表的字段是有长度限制的,这里整个SQL的长度是不能超过日志字段的长度的。6、使用UNIONALL替代UNION 在使用联合查询的时候,很多时候我们会使用到UNIONALL或者UNION来联合多个表,进行汇总。那么UNIONALL和UNION的区别是什么呢?这两个的区别是UNIONALL会返回联合后的所有行记录,而UNION是会进行去重后返回。 比如说我们有两张表teacher和student,里面的数据分别是下面 这里这两张表当中,存在相同的一条数据,就是(4,马六)这一条数据,我们可以看看使用UNIONALL和UNION的效果 可以看到第二次的查询结果中已经少了一行,说明我们上面说的UNION会去重的逻辑是存在的,而且去重是全字段都相同的时候才会被去重。7、用精确的字段代替 另一个比较影响性能的点是使用,很多小伙伴为了省事,在编写查询语句的时候,会使用来代替所有的字段,其实并不是说这种写法有什么问题,只是这种写法有点不可控,使用表示要查询所有字段,当我们的表是一个很简单的表,而且里面的字段都是一些小字段的时候,使用完全是可以的。 但是如果是对于一些大表特别是有text这种大字段的表,或者是一些敏感数据的表,我们还使用号去查询数据的话,就会有很大的问题了,一方面是有安全隐患,一方面还是增加磁盘,内存和网络的传输,完全得不偿失。8、给必要的字段增加索引 索引作为数据库里面一个很重要的内容,相比大家都不陌生,给必要的字段加上索引也是很有必要的,除了主键索引,我们还可以添加聚簇索引和唯一索引,关于索引的内容感兴趣的可以去看看我们的这篇文章面试官问我索引为什么这快?我好像解释不清楚了,这里阿粉就不细说了。总结 后端程序员除了跟服务器打交道之外最多的就是跟数据库打交道了,如何在数据库层面提效也是一个长久的话题,这也是为什么数据库能得到发展的原因,从关系型数据库到NoSQL数据库,从MySQL到ClickHouse,数据库行业也在长久的发展。