sql优化学习

mysql 查询的执行顺序:from where group by having select order by

首先我们要明白几点、优化sql其实也就是优化索引,以及减少对数据库的访问,尽量通过Java去操作,尽量不用很长很复杂的sql去执行,拆分为多个sql,如果表有升级记得删除索引重新加上索引

注意sql查询慢的原因一般都是:引起filesort文件排序,增加磁盘io消耗

对于慢sql的记录我们可以开启慢查询日志

一、Order by排序优化

当需要对age,money进行排序时可以加上复合索引,然后 select id,age,money from eap order by age,money,这个时候使用的是usIng Index,orderby的顺序需要和索引的顺序相同

二、子查询用连接查询替代

三、Or操作

如果我们是用or关联两个字段,那么这两个字段都要有索引,如果一个有一个没有,则索引失效,加一个复合索引也不行

但可以用union替换or操作,提示查询效率

四、limit分页查询

limit 1000,10虽然我们只取出10条信息,但它需要首先排序这些信息然后取出10条,我们可以通过

      select * from eap order by id limit 1000,10,这种优化方式,提示查询速率

虑筛选字段(title)上加索引

       title字段加索引  (此效率如何未加验证)

先查询出主键id值

select id,title from collect where id>=(select id from collect order by id limit 90000,1) limit 10;

原理:先查询出90000条数据对应的主键id的值,然后直接通过该id的值直接查询该id后面的数据。

五、like

在使用LIKE关键字进行查询的查询语句中,如果匹配字符串的第一个字符为“%”,索引不会起作用。只有“%”不在第一个位置索引才会起作用。

六、in连接解释

1、两个表选哪个为驱动表,表面是可以以数据量的大小作为依据,但是实际经验最好交给mysql查询优化器自己去判断。

  例如:  select * from a where id in (select id from b );  

        对于这条sql语句它的执行计划其实并不是先查询出b表的所有id,然后再与a表的id进行比较。
mysql会把in子查询转换成exists相关子查询,所以它实际等同于这条sql语句:select * from a where exists(select * from b where b.id=a.id );

        而exists相关子查询的执行原理是: 循环取出a表的每一条记录与b表进行比较,比较的条件是a.id=b.id . 看a表的每条记录的id是否在b表存在,如果存在就行返回a表的这条记录。

exists查询有什么弊端?
      由exists执行原理可知,a表(外表)使用不了索引,必须全表扫描,因为是拿a表的数据到b表查。而且必须得使用a表的数据到b表中查(外表到里表中),顺序是固定死的。

如何优化?
      建索引。但是由上面分析可知,要建索引只能在b表的id字段建,不能在a表的id上,mysql利用不上。

这样优化够了吗?还差一些。
      由于exists查询它的执行计划只能拿着a表的数据到b表查(外表到里表中),虽然可以在b表的id字段建索引来提高查询效率。
但是并不能反过来拿着b表的数据到a表查,exists子查询的查询顺序是固定死的。

为什么要反过来?
       因为首先可以肯定的是反过来的结果也是一样的。这样就又引出了一个更细致的疑问:在双方两个表的id字段上都建有索引时,到底是a表查b表的效率高,还是b表查a表的效率高?

该如何进一步优化?
       把查询修改成inner join连接查询:select * from a inner join b on a.id=b.id; (但是仅此还不够,接着往下看)

为什么不用left join 和 right join?
       这时候表之间的连接的顺序就被固定住了,比如左连接就是必须先查左表全表扫描,然后一条一条的到另外表去查询,右连接同理。仍然不是最好的选择。

为什么使用inn