1、避免使用select * from,如果select中的列不全是索引列,那么就会导致索引失效
select * 与 select a
例如,有一个表为t(a,b,c,d,e,f),其中,a为主键,b列有索引。
那么,在磁盘上有两棵 B+ 树,即聚集索引和辅助索引(包括单列索引、联合索引),分别保存(a,b,c,d,e,f)和(a,b),
如果查询条件中where条件可以通过b列的索引过滤掉一部分记录,查询就会先走辅助索引,如果用户只需要a列和b列的数据,
直接通过辅助索引就可以知道用户查询的数据。
如果用户使用select *,获取了不需要的数据,
则首先通过辅助索引过滤数据,然后再通过聚集索引获取所有的列,这就多了一次b+树查询,速度必然会慢很多。
这里有一个有一个知识点,就是Mysql中的innodb引擎下,一般主键是非聚簇索引,节点存储数据相关信息,其它索引如(a,b)叶子节点上没有数据行信息,在通过b索引查了一次之后,还需要再查一次聚簇索引获取所有列的信息,如果查询列只有索引列,就没有这一步。
2、用union all代替union
union all比union多了一步去重,在某些情况下可以考虑这一步没有必要的话,可以去掉。
3、小表驱动大表
这种情况适用于order中的数据量很大,user表中数据少,因为会优先执行in 里面的sql语句。
select * from order where user_id in (select user_id from users where status = 1);
这种情况适用于order中数据量很小的情况,因为会先执行exists左边的语句。
select * from order where exists (select 1 from users where user_id = 1);
4、批量插入
对于insert语句有很多条不能放在循环里,因为网络IO会消耗大量资源,慢。可以动态拼接sql,但是不宜过长,一是慢而是数据库某些版本的sql长度有限制。如果使用的是MyBatis框架,其中mapper没有提供批量插入的方法,则直接创建sqlsessionfactory并指定为批处理,后面再使用mapper执行插入或者更新方法就会自动是批处理。
如果使用的是MyBatisPlus框架,直接使用BaseMapper中的批量方法。
5、in中值不能太多
把in里面的值分开,多线程分批处理。
6、高效分页
select * from order limit 200000,2
会查出2000052条数据,然后丢弃其它的只留下两条。
应该尽量在索引列上进行大小比较,并且要求此索引列自增,例如
select * from order where id>2000000 limit 2;
或者使用between and,使用时要注意使用的列为唯一索引。
7、使用连接查询代替子查询
子查询会用到临时表
8、join的表的数量不一应该过多
连接条件是索引的时候,连接条件多了,会让解释器选错索引
9、left join 与 inner join
inner join会自动选择数据量少的表驱动大的表,left join 会先跑左边的表。
10、控制索引数量
索引会占空间,在insert、delete、update的时候会修改索引,降低性能,能建联合索引就不要建单个索引,
11、合理的字段类型
对于变化的字段就用varchar,不变的就用char
12、group by的使用
如果用了having过滤数据,则可使用where先过滤数据
13、索引优化
https://blog.csdn.net/ZGL_cyy/article/details/132941360