SQL优化

  

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,左边表结果尽量小

  1. Inner join 内连接,在两张表进行连接查询时,只保留两张表中完全匹配的结果集
  2. left join 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录。
  3. right join 在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录。

都满足SQL需求的前提下,推荐优先使用Inner join(内连接),如果要使用left join,左边表数据结果尽量小,如果有条件的尽量放到左边处理。

8:使用exists

假设表A表示某企业的员工表,表B表示部门表,查询所有部门的所有员工,很容易有以下SQL:

  1. 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

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

  1. List<> resultSet ;

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

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

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

  5. resultSet.add(A[i]);

  6. break;

  7. }

  8. }

  9. }

显然,除了使用in,我们也可以用exists实现一样的查询功能,如下:

  1. 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表做循环.

同理,可以抽象成这样一个循环:

  1. List<> resultSet ;

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

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

  4. if(A[i].deptId==B[j].deptId) {

  5. resultSet.add(A[i]);

  6. break;

  7. }

  8. }

  9. }

数据库最费劲的就是跟程序链接释放。假设链接了两次,每次做上百万次的数据集查询,查完就走,这样就只做了两次;相反建立了上百万次链接,申请链接释放反复重复,这样系统就受不了了。即mysql优化原则,就是小表驱动大表,小的数据集驱动大的数据集,从而让性能更优。

因此,我们要选择最外层循环小的,也就是,如果B的数据量小于A,适合使用in,如果B的数据量大于A,即适合选择exist

原文地址:https://www.cnblogs.com/bulrush/p/12573958.html