编写高质量SQL语句的30条建议
1、查询SQL尽量不要使用select *,而是select具体字段
反例:select * from employee;
正例:select id,name from employee;
理由:只取需要的字段,节省资源、减少网络开销。
select *进行查询时,很可能就不会使用到覆盖索引了,就会造成回表查询
2、如果知道查询结果只有一条或者只要最大/最小一条记录,建议用limit 1
反例:select id,name from employee where name=jay
正例:select id,name from employee where name='jay' limit 1;
理由:加上limit 1 后,只要找到了对应的一条记录,就不会继续向下扫描了,效率将会大大提高。
3、应尽量避免在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可能会使索引失效,从而全表扫描。
4、优化limit分页
反例:select id, name, age from employee limit 10000,10
正例:select id, name from employee whereid>10000 limit 10;
理由:当偏移量最大的时候,查询效率就会越低,因为Mysql并非是跳过偏移量直接去取后面的数据,而是先把偏移量+要取的条数,然后再把前面偏移量这一段的数据抛弃掉再返回的。
5、优化你的like语句
反例:select userld, name from user where userld like '% 123';
正例:select userld, name from user where userld like '123%;
理由:日常开发中,如果用到模糊关键字查询很容易想到like,但是like很可能让你的索引失效。把%放前面,并不走索引;把%放关键字后面,还是会走索引的。
6、使用where条件限定要查询的数据,避免返回多余的行
反例:
List<Long> userlds = sqlMap. queryList("select userld from user where isVip=1");
boolean isVip = userlds.contains(userld)
正例:
Long userld = sqlMap.queryObject("select userld from
user where userld='userld' and isVip='1'")
boolean isVip = userld! =null;
理由:需要什么数据,就去查什么数据,避免返回不必要的数据,节省开销。
7、尽量避免在索引列上使用mysqI的内置函数
反例:
select userld, loginTime from loginuser where Date_ADD(loginTime, interval 7
DAY) >=now();
正例:
explain select userld, loginTime from loginuser where loginTime >=
Date ADD(NOW(), INTERVAL -7 DAY);
理由:索引列上使用mysql的内置函数,索引失效;如果索引列不加内置函数,索引还是会走的。
8、应尽量避免在 where 子句中对字段进行表达式操作,这将导致系统放弃使用索引而进行全表扫
反例:
select * from user where age-1 =10;
正例:
select * from user where age =11;
理由:虽然age加了索引,但是因为对它进行运算,索引直接迷路。
9、Inner join、left join、 right join,优先使用
Inner join,如果是left join,左边表结果尽量小
10、应尽量避免在 where 子句中使用!=或 >操作符,否则将引擎放弃使用索引而进行全表扫描。
11、使用联合索引时,注意索引列的顺序,一般遵循最左匹配原则
反例:
select * from user where age = 10;
正例:
//符合最左匹配原则
select * from user where userid=10 and age =10;
//符合最左匹配原则
select * from user where userid =10;
理由:联合索引不满足最左原则,索引一般会失效,但是这个还跟Mjsql优化器有关的。(案例表结构:userid在age之前)
12、对查询进行优化,应考虑在 where 及orderby 涉及的列上建立索引,尽量避免全表扫描
13、如果插入数据过多,考虑批量插入
14、在适当的时候,使用覆盖索引
15、慎用distinct关键字
16、删除冗余和重复索引
17、如果数据量较大,优化你的修改/删除语句
18、where子句中考虑使用默认值代替null
19、不要有超过5个以上的表连接
理由:
(1)连表越多,编译的时间和开销也就越大。
(2)把连接表拆开成较小的几个执行,可读性更高。
(3)如果一定需要连接很多表才能得到数据,那么意味着糟糕的设计了。
20、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)来决定主查询的数据结果是否得意保留。
21、尽量用 union all 换 union
22、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型。
23、索引不宜太多,一般5个以内
24、尽量避免向客户端返回过多数据量
25、索引不适合建在有大量重复数据的字段上,如性别这类型数据库字段。
26、当在SOL语句中连接多个表时,请使用表的别名,并把别名前缀于每一列上,这样语义更加清晰。
27、尽可能使用varchar/nvarchar 代替char/nchar
28、为了提高group by 语句的效率,可以在执行到该语句前,把不需要的记录过滤掉。
29、如何字段类型是字符串,where时一定用引号括起来,否则索引失效。
30、使用explain 分析你SOL的计划日常开发写SQL的时候,尽量养成一个习惯。
用explain分析一下你写的SQL,尤其是走不走索引这一块。
explain select * from user where userid=10086 or age =18;
版权保护: 本文由 绿茶加糖-郭保升 原创,转载请保留链接: https://www.guobaosheng.com/shujuku/82.html
- 上一篇:35个必掌握SQL语句,一口气全学完!
- 下一篇:SQL编程规范