MySQL SQL优化

5.7 小表驱动大表

在这里插入图片描述

EXISTS [ɪɡˈzɪsts]语法SELECT ...FROM table WHERE EXISTS (subquery)

该语法可以理解为:将主查询的数据,放到子查询中做条件验证,根据验证结果(TRUE或FALSE)来决定主查询的数据结果是否得以保留

提示

  • EXSTS(subquey) 只返回TRUE或FALSE,因此子查询中的SELECT * 也可以是 SELECT 1 或select ‘X’,官方说法是实际执行时会忽略SELECT清单,因此没有区别。
  • EXISTS子查询的实际执行过程可能经过了优化而不是我们理解上的逐条对比,如果担忧效率问题,可进行实际检验以确定是否有效率问题。
  • EXISTS子查询往往也可以用条件表达式,其他子查询或者JOIN来替代,何种最优需要具体问题具体分析

in和exists用法
在这里插入图片描述

5.8 Order by优化

1、ORDER BY之后子句,尽量使用Index方式排序,避免使用FileSort方式排序

建表:

create table tblA(
    #id int primary key not null auto_increment,
    age int,
    birth timestamp not null
);

insert into tblA(age, birth) values(22, now());
insert into tblA(age, birth) values(23, now());
insert into tblA(age, birth) values(24, now());

create index idx_A_ageBirth on tblA(age, birth);

//查询
mysql> select * from tblA;
+------+---------------------+
| age  | birth               |
+------+---------------------+
|   22 | 2021-04-04 19:31:45 |
|   23 | 2021-04-04 19:31:45 |
|   24 | 2021-04-04 19:31:45 |
+------+---------------------+
3 rows in set (0.00 sec)

mysql> show index from tblA;
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tbla  |          1 | idx_A_ageBirth |            1 | age         | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |
| tbla  |          1 | idx_A_ageBirth |            2 | birth       | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)

关注点:是order by之后会不会产生Using filesort
在这里插入图片描述
在这里插入图片描述
MySQL支持二种方式的排序,FileSort和lIndex,Index效率高,它指MySQL扫描索引本身完成排序。FileSort方式效率较低。

ORDER BY满足两情况,会使用Index方式排序:

  • ORDER BY语句使用索引最左前列。
  • 使用where子句与Order BY子句条件列组合满足索引最左前列。

2、尽可能在索引上完成排序操作,遵照建索引的最佳左前缀

3、如果不在索引列上,mysql的filesort有两种算法(自动启动)

  • 双路排序

    MySQL4.1之前是使用双路排序,字面意思就是两次扫描磁盘,最终得到数据,读取行指针和OrderBy列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读对应的数据输出。

    从磁盘取排序字段,在buffer进行排序,再从磁盘取其他字段。

    取一批数据,要对磁盘进行了两次扫描,众所周知,I\O是很耗时的,所以在mysql4.1之后,出现了第二种改进的算法,就是单路排序

  • 单路排序

    从磁盘读取查询需要的所有列,按照order by列在buffer对它们进行排序,然后扫描排序压的列表进行输出,它的效率更快一些,避免了第二次读取数据。并且把随机IO变成了顺序IO,但是它会使用更多的空间,因为它把每一行都保存在内存中了

  • 结论及引申出的问题

    由于单路是后出的,总体而言好过双路

    但是用单路有问题,在sort_buffer中,方法B比方法A要多占用很多空间,因为方法B是把所有字段都取出,所以有可能取出的数据的总大小超出了sort_buffer的容量,导致每次只能取sort_buffer容量大小的数据,进行排序(创建tmp文件,多路合并),排完再取取
    sort_buffer容量大小,再排……从而多次I/O。

    本来想省一次I/O操作,反而导致了大量的I/O操作,反而得不偿失

4、优化策略

  • 增大sort_buffer_size参数的设置
  • 增大max_length_for_sort_data参数的设置
  • Why?
    在这里插入图片描述
    5、小总结:
    在这里插入图片描述

5.9 Group by优化

group by实质是先排序后进行分组,遵照索引建的最佳左前缀。
当无法使用索引列,增大max_length_for_sort_data参数的设置 + 增大sort_buffer_size参数的设置。
where高于having,能写在where限定的条件就不要去having限定了

  • 在group by后面加个order by null 就可以防止排序
    在这里插入图片描述

  • 有些情况下,可以使用连接来替代子查询。因为使用join, MySQL不需要在内存中创建临时表

    #简单处理方式
    select * fom dept,emp where dept.deptno=emp.deptno;
    #左连接更优
    select * from dept left join emnp on dept.deptno=emp.deptno;
    

你可能感兴趣的:(mysql,sql,数据库)