1、查询SQL尽量不要使用select *,而是select具体字段。
理由:
-
只取需要的字段,节省资源、减少网络开销。
-
select * 进行查询时,很可能就不会使用到覆盖索引了,就会造成回表查询。
2、如果知道查询结果只有一条或者只要最大/最小一条记录,建议用limit 1
理由:
-
加上limit 1后,只要找到了对应的一条记录,就不会继续向下扫描了,效率将会大大提高。
-
当然,如果name是唯一索引的话,是不必要加上limit 1了,因为limit的存在主要就是为了防止全表扫描,从而提高性能,如果一个语句本身可以预知不用全表扫描,有没有limit ,性能的差别并不大。
3、应尽量避免在where子句中使用or来连接条件
应当使用两条SQL语句。在程序中控制。
理由:
-
使用or可能会使索引失效,从而全表扫描。
对于or+没有索引的age这种情况,假设它走了userId的索引,但是走到age查询条件时,它还得全表扫描,也就是需要三步过程:全表扫描+索引扫描+合并 如果它一开始就走全表扫描,直接一遍扫描就完事。mysql是有优化器的,处于效率与成本考虑,遇到or条件,索引可能失效,看起来也合情合理。
4、优化limit分页
select * from articles where id >(select id from articles limit 170500,1) limit 500
这种方法的好处是首先通过id索引快速定位到了分页数据的起始位置(避免了全文检索),并且用limit 方法快速获取了从起始位置往后的500个数据。
最优:select * from articles where id between (select id from articles limit 170000,1) and (select id from articles limit 170500,1)
between and的方法相当于也是利于id索引的优势,但是同时定位了分页的起始和终止的位置,截取了中间的信息,因此速度会更快.
5:尽量避免在索引列上使用mysql的内置函数
会导致索引失效
6:应尽量避免在where子句中对字段进行表达式操作,这将导致系统放弃使用索引而进行全表扫
7:Inner join 、left join、right join,优先使用Inner join,如果是left join,左边表结果尽量小
- Inner join 内连接,在两张表进行连接查询时,只保留两张表中完全匹配的结果集
- left join 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录。
- right join 在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录。
都满足SQL需求的前提下,推荐优先使用Inner join(内连接),如果要使用left join,左边表数据结果尽量小,如果有条件的尽量放到左边处理。
8:使用exists
假设表A表示某企业的员工表,表B表示部门表,查询所有部门的所有员工,很容易有以下SQL:
-
select * from A where deptId in (select deptId from B);
这样写等价于:
先查询部门表B
select deptId from B
再由部门deptId,查询A的员工
select * from A where A.deptId = B.deptId
可以抽象成这样的一个循环:
-
List<> resultSet ;
-
for(int i=0;i<B.length;i++) {
-
for(int j=0;j<A.length;j++) {
-
if(A[i].id==B[j].id) {
-
resultSet.add(A[i]);
-
break;
-
}
-
}
-
}
显然,除了使用in,我们也可以用exists实现一样的查询功能,如下:
-
select * from A where exists (select 1 from B where A.deptId = B.deptId);
因为exists查询的理解就是,先执行主查询,获得数据后,再放到子查询中做条件验证,根据验证结果(true或者false),来决定主查询的数据结果是否得意保留。
那么,这样写就等价于:
select * from A,先从A表做循环
select * from B where A.deptId = B.deptId,再从B表做循环.
同理,可以抽象成这样一个循环:
-
List<> resultSet ;
-
for(int i=0;i<A.length;i++) {
-
for(int j=0;j<B.length;j++) {
-
if(A[i].deptId==B[j].deptId) {
-
resultSet.add(A[i]);
-
break;
-
}
-
}
-
}
数据库最费劲的就是跟程序链接释放。假设链接了两次,每次做上百万次的数据集查询,查完就走,这样就只做了两次;相反建立了上百万次链接,申请链接释放反复重复,这样系统就受不了了。即mysql优化原则,就是小表驱动大表,小的数据集驱动大的数据集,从而让性能更优。
因此,我们要选择最外层循环小的,也就是,如果B的数据量小于A,适合使用in,如果B的数据量大于A,即适合选择exist。