Mysql sql优化

目录

目的

目标

explain

优化

避免使用select *

用union all代替union

小表驱动大表(in与exists)

批量操作

多使用limit

in中值太多

不使用%前缀模糊查询

不在where子句中进行表达式操作

避免隐式类型转换

联合索引遵守最左前缀法则

inner join、left join、right join、full join

count(*)与count(1)

避免is null /is not null

避免在 where 子句中使用 or

去重distinct过滤字段要少


目的

        1.提高资源的利用率

        2.提高系统的吞吐量

        3.同时满足更多用户的在线需求

目标

        1.减少磁盘IO

        2.减少网络带宽

        3.降低cpu消耗

explain

        在select语句之前增加explain关键字,执行后MySQL就会返回执行计划的信息,而不是执行sql。但如果from中包含子查询,MySQL仍会执行该子查询,并把子查询的结果放入临时表中。

EXPLAIN SELECT
    tp.*, col.course_title couserName,
    col.course_type_name courseName,
    col.course_theme_name courseTheme,
    col.course_type_name courseType
FROM
    le_teaching_plan tp
JOIN le_course col ON tp.course_id = col.id
WHERE
    tp.id = '0293abd864954d4b93f163e473924032'

1.id:id列的编号是select的序列号,有几个select就有几个id

2.select_type:

        simple:不包含子查询和union的简单查询

        primary:复杂查询中最外层的select

        subquery:包含在select中的子查询

        derived:包含在from子句中的子查询

        union:在union中的第二个和随后的select,UNION RESULT为合并的结果

3.table:表示当前行访问的是哪张表

4.partitions:查询将匹配记录的分区,对于非分区表为null

5.type:此列表示关联类型或访问类型。也就是MySQL决定如何查找表中的行。依次从最优到最差分别为:system > const > eq_ref > ref > range > index > all

6.possible_keys:此列显示在查询中可能用到的索引

7.key:此列显示MySQL在查询时实际用到的索引

8.key_len:索引里使用的字节数

9.ref:显示key列记录的索引中,表查找值时使用到的列或常量

10.rows:查询中估计要读取的行数

11.Extra:额外信息

优化

避免使用select *

        使用*号多查出来的数据,通过网络IO传输的过程中,也会增加数据传输的时间;同时*不走覆盖索引,导致性能降低。

        通过索引值可以直接找到要查询字段的值,而不需要通过主键值回表查询,那么就叫覆盖索引。

用union all代替union

(select * from user where id=1)
union
(select * from user where id=2);

        使用union关键字后,可以获取排重后的数据(排重的过程需要遍历、排序和比较,它更耗时,更消耗cpu资源)

        使用union all关键字,可以获取所有数据,包含重复的数据

小表驱动大表(in与exists)

        用小表的数据集驱动大表的数据集

select * from order
where user_id in (select id from user where status=1)

select * from order
where exists (select 1 from user where order.user_id = user.id and status=1)

sql语句中包含了in关键字,则它会优先执行in里面的子查询语句,然后再执行in外面的语句。

sql语句中包含了exists关键字,它优先执行exists左边的语句(即主查询语句)。然后把它作为条件,去跟右边的语句匹配。如果匹配上,则可以查询出数据。如果匹配不上,数据就被过滤掉了。

in 适用于左边大表,右边小表;exists 适用于左边小表,右边大表。

批量操作

        尽量只远程请求一次数据库,sql性能会得到提升,数据量越多,提升越大;需要注意的是,不建议一次批量操作太多的数据,如果数据太多数据库响应也会很慢。批量操作需要把握一个度,建议每批数据尽量控制在500以内。如果数据多于500,则分多批次处理

多使用limit

为了使explain中type列达到const类型。当只需要一条数据的时候,使用limit 1,如果加上limit1,查找到就不用继续往后找了

in中值太多

select id,name from category
where id in (1,2,3...100000000);

不使用%前缀模糊查询

select * from order where name like '%name%'

使用%前缀会导致索引失效而进行全表扫描;

如果需要使用%name%,可以使用全文索引

创建全文索引

alter table order add fulltest index `idx_name` (`name`);

使用全文索引

select * from order where match(name) against('zhangsan')

不在where子句中进行表达式操作

select user_id,user_project from user_base where age*2=36;

字段就行了算术运算,这会造成引擎放弃使用索引

避免隐式类型转换

        where子句中出现name字段的类型和传入的参数类型不一致的时候发生的类型转换,会导致索引失效

联合索引遵守最左前缀法则

        如含有字段id、name、school,可以直接用id字段,也可以id、name这样的顺序,但是name;school都无法使用这个索引。

        联合索引存在范围查询,比如between、>、<等条件时,会造成后面的索引字段失效

inner join、left join、right join、full join

left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 

right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录

inner join(内连接) 返回两个表中联结字段相等的行

full join(全连接)返回两个表中没有相等的行

count(*)与count(1)

如果表中多个列并且没有主键,则count(1)的执行效率优于count(*);

如果有主键,则select count(主键)的执行效率是最优的;如果表中只有一个字段,则select count(*)最优。

避免is null /is not null

select id from t where num is null

        尽量避免在 where 子句中对字段进行 null 值判断,使用is null 或者is not null 理论上都会走索引,存在Null值会导致mysql优化器处理起来比较复杂,容易导致引擎放弃使用索引而进行全表扫描

null值很难查询优化且占用额外的索引空间,推荐默认数字0代替null

避免在 where 子句中使用 or

select id from t where num=10 or num=20

改为:

select id from t where num=10
union all
select id from t where num=20

        where 子句中使用 or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描;如果要利用索引,则OR之间的每个条件列都必须要用到索引。

去重distinct过滤字段要少

当查询很多字段时,如果使用distinct,数据库引擎就会对数据进行比较,过滤掉重复数据,然而这个比较、过滤的过程会占用系统资源,如cpu时间

你可能感兴趣的:(MySQL,Java,MyBatis,数据库)