作为后端程序员,可以说每天都要和数据库打交道,不管是MySQL、Oracle还是SQLServer,毫无疑问SQL是逃不掉的,所以在日常工作中优化SQL的性能非常重要。今天阿粉就带大家看看每个后端程序员都应该知道的提高查询性能的十个技巧。1.使用Exists而不是子查询。日常工作中不可避免地要用到子查询。很多时候我们的用法是这样的:SELECTId,NameFROMEmployeeWHEREDeptIdIn(SELECTIdFROMDepartmentWHERENamelike'%Management%');相信大家平时都是这样使用的。其实还有更好的办法,如下图:SELECTId,NameFROMEmployeeWHEREDeptIdExist(SELECTIdFROMDepartmentWHERENamelike'%Management%');这里我们使用exist关键字Word而不是In关键字。当然,如果数据量不大,这两种方法都可以,但是当数据量很大时,exist方法会比in方法效率高很多。因为Exist函数会根据查询结果返回一个布尔值,所以会快很多。2、正确使用JOIN代替子查询除了以上几种情况,在某些场景下我们还可以使用JOIN代替子查询。毕竟子查询的效果很差,如下图:SELECTId,NameFROMEmployeeWHEREDeptIdin(SELECTIdFROMDepartmentWHERENamelike'%Management%');使用JOIN如下:SELECTEmp.Id,Emp.Name,Dept.DeptNameFROMEmployeeEmpRIGHTJOINDeptonEmp.DeptId=Dept.IdWHEREDept.DeptNamelike'%Management%';3.用Where代替不必要的Having。相信大家都很会用Where,但是平时你可能用的不多。阿芬在这里只能说一句:我用的不多,挺好的!至于Having,能用不用不用,万不得已不用。说实话,阿芬干了这么多年,还真没有动用过Having的场面。我们先看下面的例子:HavingSELECTEmp.Id,Emp.Name,Dept.DeptName,Emp.SalaryFROMEmployeeEmpRIGHTJOINDepartmentDeptonEmp.DeptId=Dept.IdGROUPBYdept.DeptNameHAVINGEmp.Salary>的用法=20000;使用WhereSELECTEmp.Id,Emp.Name,Dept.DeptName,Emp.SalaryFROMEmployeeEmpRIGHTJOINDepartmentDeptonEmp.DeptId=Dept.IdWHEREEmp.Salary>=20000;为什么Having的性能没有Where高?是因为Where是精确匹配,而Having需要和GroupBy配合使用。只要涉及到GroupBy,效率就不会高。4.使用精确的字段类型。有些朋友为了系统的可扩展性,根本不知道数据库字段的类型设置什么,所以都用char或者varchar。我总觉得这样比较灵活,但往往这个时候是对的。系统最大的隐患。使用时间类型字段时,需要设置为DateTime而不是varchar;使用flag是否删除时,应该使用tinyint,能使用varchar就不要使用char;对于大字段,文本需要分开,所以在查询的时候不会影响性能;对于那些可以设置为唯一键的,需要设置为唯一键,因为你在程序中永远避免不了脏数据,你必须保证数据层的一致性。5.使用批处理而不是循环。在插入数据的时候,我们可以使用values来批量插入,而不是通过循环查询单条数据,如下图://NotadvisableFor(Inti=0;i<=5;i++){INSERINTOTable1(Id,Value)Values(i,'Value'+i);}//推荐INSERTINTOTable1(Id,Value)Values(1,Value1),(2,Value2),(2,Value3),(4,值4),(5,值5);不过需要注意的是,values后面的个数也是有限制的,所以两者可以结合使用,具体的个数可以根据要执行的表字段个数来决定。另外,这里还有一点需要注意。很多系统会在底层做操作日志,很多时候可能是在SQL层面。这时需要注意记录操作日志的表中字段的长度。这里,整个SQL的长度不能超过日志字段的长度。6.使用UNIONALL而不是UNION在使用联合查询时,我们经常使用UNIONALL或者UNION将多个表合并起来进行汇总。那么UNIONALL和UNION有什么区别呢?两者的区别在于,UNIONALL会返回并集后的所有行记录,而UNION会在去重后返回。比如我们有teacher和student两个表,里面的数据是这样的:在这两个表中,有相同的数据,就是(4,马六)。我们可以看到使用UNIONALL和UNION的效果。可以看到第二个查询结果中少了一行,说明上面的UNION去重逻辑是存在的,去重只是在所有字段都相同的情况下。7.用精确字段替换*影响性能的另一点是*的使用。为了省事,很多朋友在写查询语句的时候都会用*来代替所有的字段。其实并不是说这种写法有什么问题。问题是这种写法有点不可控。使用*表示查询所有字段。当我们的表是一个很简单的表,里面的字段都是小字段的时候,完全可以使用*。但是,如果我们使用*号来查询一些大表的数据,尤其是文本等大字段,或者敏感数据的表,就会出现很大的问题。一方面,存在安全问题。隐患一方面是增加了磁盘、内存和网络的传输,完全得不偿失。8.为必填字段添加索引。索引作为数据库中非常重要的内容,大家都很熟悉。还需要为必要的字段添加索引。除了主键索引,我们还可以添加聚簇索引和唯一索引。综上所述,后端程序员除了跟服务器打交道,跟数据库打交道最多的。如何在数据库层面提高效率也是一个长期的话题,这也是数据库为什么能够发展起来的原因,从关系型数据库到NoSQL数据库,从MySQL到ClickHouse,数据库行业也是发展了很久。
