编写高质量SQL语句的50条建议(满满的都是干货)

在数据库管理和开发中,SQL(Structured Query Language)是不可或缺的核心技能。无论是进行数据的增删改查,还是优化数据库性能,编写高质量的SQL语句都是至关重要的。以下,我将分享20条编写高质量SQL语句的建议,旨在帮助开发人员和数据库管理员提升效率,减少错误,并优化数据库性能。

1. 明确查询目的

在编写SQL之前,首先要明确查询的目标是什么。是获取某个具体的数据集,还是进行数据的汇总分析?明确目标有助于构建更加精确和高效的查询。

2. 使用合适的SELECT列

避免使用`SELECT *`,除非确实需要所有列。指定需要的列可以减少数据传输量,提高查询效率,并有助于避免不必要的列暴露给前端应用。

3. 利用表别名

在查询中,为表设置别名可以使SQL语句更加简洁易读,特别是在涉及多表连接时。同时,别名还可以帮助解决列名冲突的问题。

4. 合理使用WHERE子句

WHERE子句用于过滤记录,确保只返回满足条件的数据。合理使用索引列作为过滤条件可以显著提升查询速度。

5. 优化JOIN操作

在进行表连接时,确保连接条件被索引覆盖,且连接顺序合理。内连接(INNER JOIN)优先于外连接(LEFT/RIGHT JOIN),因为内连接通常更高效。

6.使用子查询需谨慎

子查询在某些情况下非常有用,但过多的子查询会增加查询的复杂度,降低性能。考虑是否可以使用JOIN替代子查询,或者将子查询作为临时表(CTE)处理。

7. 利用索引

索引是加速数据库查询的关键。确保在WHERE子句、JOIN条件、ORDER BY和GROUP BY子句中使用的列都被索引。同时,注意索引的维护,避免过多索引带来的写操作负担。

8. 避免在WHERE子句中使用函数

在WHERE子句中对列使用函数会阻止数据库利用索引,导致查询性能下降。尽可能在查询外部处理数据转换。

9.合理使用聚合函数

聚合函数如SUM、AVG、COUNT等是处理数据汇总的强大工具。但使用时要注意,它们会强制数据库进行全表扫描或至少扫描大部分数据,因此要确保查询的列已被索引或查询本身合理。

10.利用GROUP BY的HAVING子句

HAVING子句是对GROUP BY结果集的进一步过滤。与WHERE子句不同,HAVING可以应用于聚合函数的结果。合理使用HAVING子句可以进一步减少结果集的大小。

11.使用DISTINCT去除重复数据

当需要去除查询结果中的重复行时,可以使用DISTINCT关键字。但请注意,DISTINCT操作会消耗额外的计算资源,特别是在处理大数据集时。

12.考虑使用LIMIT限制结果集

当只需要部分数据时,使用LIMIT子句可以显著减少数据传输和处理时间。这对于分页显示数据尤其有用。

13.避免在SELECT中使用计算字段进行排序

在ORDER BY子句中使用计算字段(如`ORDER BY LENGTH(column_name)`)会阻止数据库使用索引,导致排序效率低下。如果可能,先计算并存储这些值,然后再进行排序。

14. 使用参数化查询

参数化查询不仅可以防止SQL注入攻击,还可以提高查询的重用性,从而优化性能。

15. 避免使用SELECT DISTINCT与多个列

当SELECT DISTINCT涉及多个列时,数据库需要创建临时表来存储唯一行,这会影响性能。如果可能,考虑使用其他逻辑来替代。

16. 利用EXPLAIN分析查询计划

大多数数据库管理系统都提供了EXPLAIN命令,用于分析SQL语句的执行计划。通过查看查询计划,可以了解数据库如何执行查询,并据此进行优化。

17. 避免过度使用子查询

虽然子查询在某些情况下很有用,但过度使用会导致查询性能下降。考虑将子查询重写为连接(JOIN)或使用临时表(CTE)来提高效率。

18.使用索引提示

在某些情况下,数据库可能无法选择最优的索引。此时,可以使用索引提示来指定数据库使用特定的索引。但请注意,这可能会降低查询的可移植性。

19. 定期审查和优化查询

数据库的性能会随着数据和查询的变化而变化。定期审查和优化查询是保持数据库高效运行的关键。

20.保持SQL语句的简洁性**

复杂的SQL语句不仅难以维护,还可能导致性能问题。尽量保持SQL语句的简洁性,避免不必要的复杂性和冗余。

21、查询SQL尽量不要使用select *,而是select具体字段反例:select * from employee;正例:select id,name from employee;

理由:只取需要的字段,节省资源、减少网络开销。select *进行查询时,很可能就不会使用到覆盖索引了,就会造成回表查询

22、如果知道查询结果只有一条或者只要最大/最小一条记录,建议用limit 1

反例:

select id,name from employee where name=jay

正例:

select id,name from employee where name='jay' limit 1;

理由:加上limit 1 后,只要找到了对应的一条记录,就不会继续向下扫描了,效率将会大大提高。

23、应尽量避免在where子句中使用or来连接条件反例:select * from user where usered=1 or age=18

正例:(使用union all  )

select * from user where usered=1 union all
select * from user where age=18

理由:使用or可能会使索引失效,从而全表扫描。

24、优化limit分页

反例:

select id, name, age from employee limit 10000,10

正例:

select id, name from employee whereid>10000 limit 10;

理由:当偏移量最大的时候,查询效率就会越低,因为Mysql并非是跳过偏移量直接去取后面的数据,而是先把偏移量+要取的条数,然后再把前面偏移量这一段的数据抛弃掉再返回的。

25、优化你的like语句

反例:

select userld, name from user where userld like '% 123';

正例:

select userld, name from user where userld like '123%;

理由:日常开发中,如果用到模糊关键字查询很容易想到like,但是like很可能让你的索引失效。把%放前面,并不走索引;把%放关键字后面,还是会走索引的。

26、使用where条件限定要查询的数据,避免返回多余的行

反例:

List<Long> userlds = sqlMap. queryList("select userld from user where isVip=1");boolean isVip = userlds.contains(userld)

正例:

Long userld = sqlMap.queryObject("select userld fromuser where userld='userld' and isVip='1'")boolean isVip = userld! =null;

理由:需要什么数据,就去查什么数据,避免返回不必要的数据,节省开销。

27、尽量避免在索引列上使用mysqI的内置函数

反例:

select userld, loginTime from loginuser where Date_ADD(loginTime, interval 7DAY) >=now();

正例:

explain select userld, loginTime from loginuser where loginTime >=Date ADD(NOW(), INTERVAL -7 DAY);

理由:索引列上使用mysql的内置函数,索引失效;如果索引列不加内置函数,索引还是会走的。

28、应尽量避免在 where 子句中对字段进行表达式操作,这将导致系统放弃使用索引而进行全表扫

反例:

select * from user where age-1 =10;

正例:

select * from user where age =11;

理由:虽然age加了索引,但是因为对它进行运算,索引直接迷路。

29、Inner join、left join、 right join,优先使用Inner join,如果是left join,左边表结果尽量小

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

31、使用联合索引时,注意索引列的顺序,一般遵循最左匹配原则

反例:

select * from user where age = 10;

正例:

//符合最左匹配原则select * from user where userid=10 and age =10;//符合最左匹配原则select * from user where userid =10;

理由:联合索引不满足最左原则,索引一般会失效,但是这个还跟Mjsql优化器有关的。(案例表结构:userid在age之前)

32、对查询进行优化,应考虑在 where 及orderby 涉及的列上建立索引,尽量避免全表扫描

33、如果插入数据过多,考虑批量插入

34、在适当的时候,使用覆盖索引

35、慎用distinct关键字

36、删除冗余和重复索引

37、如果数据量较大,优化你的修改/删除语句38、where子句中考虑使用默认值代替null

39、不要有超过5个以上的表连接理由:

  1. (1)连表越多,编译的时间和开销也就越大。
  2. (2)把连接表拆开成较小的几个执行,可读性更高。
  3. (3)如果一定需要连接很多表才能得到数据,那么意味着糟糕的设计了。

40、exist & in的合理利用假设表A表示某企业的员工表,表B表示部门表,查询所有部门的所有员工,很容易有以下SQL:

select * from A where deptld in (select deptld from B);

这样写等价于:

先查询部门表

B select deptld from B

再由部门deptld,查询A的员工

select * from A where A.deptld=B,deptld

可以抽象成这样的一个循环

List<> resultSet ;

for(int i=0;i<B.length;i++){

for(int j=0;j<A.length;j++)i

if(A[i].id==B[jl.id){

resultSet.add(Alil);

break;  

} 

}

}

可以用exists实现一样的查询功能

select * from A where exists (select 1 from B where A.deptld= B.deptld);

exists查询的理解就是,先执行主查询,获得数据后,再放到子查询中做条件验证,根据验证结果(true或者false)来决定主查询的数据结果是否得意保留。

41、尽量用 union all 换 union

42、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型。

43、索引不宜太多,一般5个以内

44、尽量避免向客户端返回过多数据量

45、索引不适合建在有大量重复数据的字段上,如性别这类型数据库字段。

46、当在SOL语句中连接多个表时,请使用表的别名,并把别名前缀于每一列上,这样语义更加清晰。

47、尽可能使用varchar/nvarchar 代替char/nchar

48、为了提高group by 语句的效率,可以在执行到该语句前,把不需要的记录过滤掉。

49、如何字段类型是字符串,where时一定用引号括起来,否则索引失效。

50、使用explain 分析你SOL的计划日常开发写SQL的时候,尽量养成一个习惯。用explain分析一下你写的SQL,尤其是走不走索引这一块。

explain select * from user where userid=10086 or age =18;
免责申明:以上文章或网盘资源均由第三方注册用户发表,不代表本站观点,如遇侵权,请与我们联系!
众嗅博客 » 编写高质量SQL语句的50条建议(满满的都是干货)

发表回复

提供最优质的资源集合

立即查看 了解详情