01、MySQL-------性能优化

目录

  • 一、影响性能的相关因素
    • 存储过程:
  • 二、sql优化
    • 1>、Mysql系统架构
    • 2>、引擎
      • 区别:
    • 3>、索引
      • 1、什么是索引?
          • 联合主键索引理解:
          • 索引长度理解:
          • 什么是慢查询?
        • 1)、索引理解
        • 2)、树高
        • 3)、在线二叉树
        • 总结
        • 4)什么是索引覆盖?
        • 5)什么是回表查询?
      • 2、Mysql索引实现
        • 1)、MyISAM索引实现
        • 2)、Innodb索引实现
        • 3)、聚簇索引
      • 3、索引的利弊
      • 4、创建索引情况
      • 5、单值索引和组合索引
        • 单值索引
        • 组合索引
    • 4>、Explain命令
      • 1)select_type:查询类型
        • 1、union
        • 2、subquery
        • 3、dependent subquery 和 dependent union
        • 4、derived
      • 2)type:联接类型
        • 1、system 和 const
        • 2、eq_ref
        • 3、ref
          • 唯一索引和非唯一索引的区别:
        • 4、ref_or_null
        • 5、index_merge
        • 6、range
        • 7、index
        • 8、ALL
      • 3)Extra详细信息
        • 1、Not exists
        • 2、Range checked for each record
        • 3、Using filesort
        • 4、Using index
        • 5、Using temporary
        • 6、Using where
        • 7、Using union
        • 8、Using index for group-by
      • 4)命令汇总:
  • 三、Join理解及优化
    • 1、Inner join
    • 2、join
    • 3、where
    • 4、left join
    • 5、straight_join
    • 6、场景优化情况
    • 7、Show profiles:比较性能
  • 四、一些索引测试
    • 1、模糊查询like
    • 2、范围查询
      • >、<
      • between
    • 3、函数
    • 4、or & and
    • 5、算数表达式
  • 五、索引使用策略及优化
    • 1、索引选择性
    • 2、前缀索引
    • 3、自增id作主键的原因
  • 六、其他优化
    • 1、order by 优化
      • 双路排序:
      • 单路排序:
      • 区别:
      • 提问:
      • 优化:

一、影响性能的相关因素

在这里插入图片描述

存储过程:

存储过程:类似可以在数据库里面写代码的一种脚本,在Mysql里面可以封装一个函数,在这个函数里面可以写很多的逻辑。可以把所有的业务放在存储过程里面去实现。

缺点:数据库很耗资源。数据库的连接是有上限的,一个请求调用一个存储过程去执行业务逻辑,意味着单个线程响应的时间变长,在并发高的情况下,每个线程返回的时间都变长的话,意味着数据库的连接很快就被用完了,那么其他现在就会进入等待,那么在应用层面就会积压很多线程,意味着应用中的线程会被耗尽,那么外面的请求就进不来了,就会导致服务器的雪崩,宕机。

在互联网应用里面并不是多么好,可以不在数据库中作的事情,就不要在数据库做

如果是传统行业,并发比较小,那么使用存储过程,在sql里面调用函数就也还行。

存储过程中调用的函数有哪些?

case when

表的设计也是影响性能的因素

账号密码修改频率低的,可以设计在一个实体类里面(一张表里面),可以放在缓存里面。

修改频率高的放在一个实体类里面,不放缓存。

应用层面的设计也是影响性能的因素

如果应用层面(代码)没设计好,所有的请求都落到数据库,那么sql优化的再好也顶不住。

代码规范、mysql规范、字段规范

二、sql优化

1>、Mysql系统架构

在这里插入图片描述

2>、引擎

区别:

数据库默认是Innodb引擎。
在这里插入图片描述

3>、索引

1、什么是索引?

能帮我们快速的定位数据,它是一种新的数据结构。

索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可以快速访问数据库表中的特定信息。

在这里插入图片描述

联合主键索引理解:

一张表永远只有一个主键索引。

除了主键索引外的其他索引都可以叫做辅助索引。

创建了索引的字段,最好设计成不为null,最好把【不是null】选项勾选上

这种情况叫做联合主键,这三个加起来才是主键,才是唯一主键,相当于 【组合索引】 一样

在这里插入图片描述

索引长度理解:

在这里插入图片描述

什么是慢查询?

mysql可以主动开一个慢查询,慢查询就是

超过指定时间的sql就会记录到日志里面

在这里插入图片描述

1)、索引理解

Navicat里面添加索引

BTREE 底层就是B+TREE

如图,给这个字段加上索引(就是把这个字段作为一个索引),然后数据库底层就会把这个字段的数据另外弄成一个二叉树的数据结构, 那么在查询的时候,如果把这个字段作为查询条件,数据库就会直接去这个二叉树数据结构找该数据。

比如表有10000条数据,有十条数据有该字段,那么没给该字段加索引前,数据库需要遍历全表,遍历这10000条数据,但是如果把该字段弄成索引,那么就只需要遍历这个二叉树而已,就是只需要遍历10次就行,效率就大大提升了。

在这里插入图片描述

2)、树高

为什么千万级别的数据,只需要3层树高就可以?

树高是4的话,有3次IO。

如图,下面的图的树高是4,IO次数就是3.(因为根节点已经被缓存了,所以IO次数就是4-1=3)

因为非叶子节点只存储指针,而每个节点属于一次io,一次io有16k,3次io就可以存有千万级别的数据对应的指针

在这里插入图片描述

这个点不是很理解?

**磁盘IO次数=树的高度 ** 还是 磁盘IO次数=树的高度-1

读取每次节点,都相当于一次的磁盘IO,搜索整棵树,路径长度为树高,磁盘IO次数=树的高度,树高越矮,磁盘IO次数越少,性能就越高。

​ 比如树高=4,经历了3次磁盘IO,因为mysql会把根节点(最上面的非叶子节点叫根节点)缓存起来,所以树高为4的话,磁盘IO次数为3。所以根节点被缓存起来后,树高就变成3,io次数也是3,所以磁盘IO次数=树的高度

为什么树高=4,只经历了3次IO

因为根节点被缓存起来了,所以树高就变成3了,IO次数也就变成3了。

问题:那第一次查询的时候,树的根节点应该还没被缓存起来,所以树高=4,IO次数也是4吗?

3)、在线二叉树

https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

磁盘IO次数=树高-1

在这里插入图片描述

总结

1、索引数据结构都是B+Tree

2、为什么不用二叉树或者红黑树呢?

​ 二叉树特定情况下会变成单向链表,性能低,可以用更好的数据结构 B+Tree。

3、有BTree和B+Tree,有什么区别,为什么选择B+Tree?

​ BTree 的非叶子节点是存实际数据的,会导致树的高度更高,那么磁盘IO次数就会越多,效率就会减低

​ B+Tree 中 非叶子节点是不存储实际的数据,存储的是值和指针(因为体积小,那么树高就更低,磁盘IO次数就更少,查询效率就更快)

​ MySql默认一次的磁盘IO是16k,16k固定的情况下,非叶子节点体积越小,能容纳数据就越多(树的阶越大,树高越矮,这个【阶】就是非叶子节点里面存的数据多少)。

​ 读取每次节点,都相当于一次的磁盘IO,搜索整棵树,路径长度为树高,磁盘IO次数=树的高度-1,树高越矮,磁盘IO次数越少,性能就越高。

​ 比如树高=4,经历了3次磁盘IO,因为mysql会把根节点(最上面的非叶子节点叫根节点)缓存起来,所以树高为4的话,磁盘IO次数为3。

4)什么是索引覆盖?

索引覆盖:辅助索引里面存的值,就已经包括了我需要的字段了(如图就是该字段是设置为辅助索引,而sql要查的字段就刚好是它),所以就不用再通过索引里面的值去回表找主键索引来查询数据,

因为辅助索引(字段)里面的值就已经是我们想要的数据了,再回表去查更多的数据也没有什么意义。

也可以简单的理解为:索引覆盖就是不用再进行回表查询,就是不用通过辅助索引的值去主键索引那里查完整的行数据。通过辅助索引就能找到对应字段的列的数据(前提:查询的该字段也是一个索引)

分析图:

在这里插入图片描述

覆盖索引的解释:

在这里插入图片描述

在这里插入图片描述

5)什么是回表查询?

一个表只有一个主键索引,其他的我们自己添加的索引都可以叫做辅助索引(比如复合索引这些都能叫做辅助索引)

回表查询就是 通过辅助索引的叶子节点里面存的主键值,到主键索引哪里找到对应的数据。

主键索引里面存的值就是完整的一行数据

在这里插入图片描述

2、Mysql索引实现

主键索引就是表的id

辅助索引就是我们自己添加的索引

1)、MyISAM索引实现

MyISAM的主键索引和辅助索引找数据的分析图

这里的主键找到数据的索引,还得根据索引的物理位置在另外的文件(.myd文件)去找具体的数据,比Innodb慢

在这里插入图片描述

2)、Innodb索引实现

Innodb的主键索引和辅助索引

在这里插入图片描述

3)、聚簇索引

聚集索引是指数据库表行中数据的物理顺序与键值的逻辑(索引)顺序相同。

跟上面分析的索引实现一样

通俗讲:
聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应

在这里插入图片描述

3、索引的利弊

索引是独立于我们数据之外的另外一种数据结构,需要存储空间的。

新增、修改等操作都要重新生成索引树,需要额外消耗资源(弊),但是相比我们查询所带来的性能的提升(利),这点消耗可以忽略不计。

索引的好处:
1,提高表数据的检索效率;
2,如果排序的列是索引列,大大降低排序成本;
3,在分组操作中如果分组条件是索引列,也会提高效率;

**索引的问题:**索引需要额外的维护成本;

字段修改的频率比查询的频率高的话,就不用建立索引。

4、创建索引情况

1,较频繁的作为查询条件的字段应该创建索引;

2,唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件;

​ 比如:查询 男和女 ,筛选完还是有海量的数据

3,更新非常频繁的字段不适合创建索引;

​ 添加索引的话,频繁修改就需要频繁重新生成索引树,消耗的资源 大于 查询的性能带来的收益

4,不会出现在WHERE 子句中的字段不该创建索引;

​ 都不作为查询条件,更没有必要添加索引

5、单值索引和组合索引

单值索引

只是把一个字段作为索引,这个就是单值索引

在这里插入图片描述

分析图:

在这里插入图片描述

组合索引

也叫复合索引

这个索引就是组合索引,组合索引用的比较多。

在这里插入图片描述

分析图:

组合索引比单值索引查询要快,但是要记得组合索引得符合【最左原则】

最左原则:where后面查询的第一个字段(不用按where顺序)要和组合索引的第一个字段相同。

在这里插入图片描述

注意这个情况,也是符合最左原则的,最左原则是要条件符合,不是说写的顺序要符合。

比如:组合索引(A、B、C),那么where条件 (ABC ACB BAC CBA 等)都是符合最左原则的。

组合索引(A、B、C),那么where条件 (BC CB BC 等)里面都没有A,查询的时候无法命中组合索引中的A索引字段,那么这个才叫做不符合最左原则

在这里插入图片描述

最佳创建组合索引

应该按照最高频的字段来创建组合索引,最大程度去覆盖到sql的查询条件,这样查询性能也能提升,生成的索引树成本也能降低。

在这里插入图片描述

4>、Explain命令

示例数据库:

数据下载:https://github.com/datacharmer/test_dbMySQL官方文档中提供的示例数据库之一:employees使用命令导入数据:
mysql -uroot -p123456 -t < employees.sql

Explain命令的作用:通过这个Explain命令来查看sql的执行计划,看能怎么对sql进行优化。

Explain命令主要来查看SQL语句的执行计划,查看该SQL语句有没有使用索引,有没有做全表扫描等。它可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理用户的SQL语句

1)select_type:查询类型

1、union

union是产生的两个记录集(字段要一样的)并在一起,成为一个新的记录集

union是将表内容拼接成一列(上下拼接),也是根据字段共同属性进行将表与表之间数据进行上下拼接
在这里插入图片描述

2、subquery

子查询中的第一个select,其select_type为SUBQUERY

在这里插入图片描述

3、dependent subquery 和 dependent union

子查询只有一个select ,第一个select 就是 subquery

子查询有多个select , 第一个 select 就是 dependent subquery,

第二个select 使用 union 连接的话,那就是 dependent union。

dependent 表示依赖的意思。表示 最外面的select 依赖于 子查询中的结果。

在这里插入图片描述

4、derived

当这个语句查询出来的数据作为别人的表的时候(查询的数据跟在from后面),相当于派生表的类型

在这里插入图片描述

2)type:联接类型

联接类型

1、system 和 const

system:查询速度最快,直接从内存中查询获取到数据

const:通过主键索引查询到数据

在这里插入图片描述

2、eq_ref

条件是:唯一索引

两张表关联的情况下(比如join之类的),查询条件的这个字段刚好是主键字段的情况下,或者是唯一字段的情况下,那么type的类型就是 eq_ref

eq_ref:表示查询的那个条件属于该表的【主键字段】或者是【唯一字段】,

因为该字段属于唯一主键,匹配这个主键成功就能直接找到对应的数据,相当于 一对一 的情况。

在这里插入图片描述

在这里插入图片描述

3、ref

条件:非唯一索引

eq_ref 的性能比 ref 要高

在这里插入图片描述

如图:两张表关联查询时,第二张表(titles)的匹配字段(emp_no)属于该表的非唯一性主键索引时,那么这张表的 type 联接类型就属于 ref。

在这里插入图片描述
解答:

把那三个字段弄成一个索引,相当于弄成一个【非唯一性主键索引】,那么在查询的时候,类型就是 ref

ref 性能比 eq_ref 低的原因就在于 ref 出现的情况是 第二张表的查询条件是 非唯一性主键索引,因为是非唯一性的,所以在索引树查询的时候,需要匹配如图的三个字段的条件才行,不像唯一性主键索引,只需要匹配一个就行,所以 ref 的性能比 re_ref 低一点。

在这里插入图片描述

唯一索引和非唯一索引的区别:

一张表永远只有一个主键索引

这种叫做唯一索引

这张表只有这个字段是主键,是主键索引,是唯一索引

在这里插入图片描述

这种叫非唯一索引

这种情况叫做联合主键,这三个加起来才是主键,三个加起来才能算是一个【唯一主键】,相当于 【组合索引】 一样

在这里插入图片描述

4、ref_or_null

出现的场景:

查询的条件字段有索引,但是设计字段的时候是可以为null,所以如果用该字段作为查询条件的话,就会出现ref_or_null的联接类型

在这里插入图片描述
在这里插入图片描述

5、index_merge

出现的场景:一张表中有多个查询条件且都有索引时,会出现 index_merge 索引合并类型。

在这里插入图片描述

针对or导致的索引失效的分析图

OR 前后只要存在非索引的列,都会导致索引失效

在这里插入图片描述

测试:
在这里插入图片描述

6、range

按指定的范围进行检索,就会显示未 range类型

在这里插入图片描述

7、index

ALL 是全表扫描数据,index 是全表扫描索引

性能上面,index 仅仅比 ALL 好上一点而已
在这里插入图片描述

8、ALL

all 类型,就是一个全表扫描,跟用没用索引一个样。

在这里插入图片描述

3)Extra详细信息

1、Not exists

查询的条件是冲突的,一个是主键,是非空的(employees),一个要查这个字段为null的,主键不可能为空,就不再继续扫描该表(dept_emp)了。

mysql根据语义发现这种查法是查不出数据的,就显示为 【Not exists】

在这里插入图片描述

2、Range checked for each record

范围查询覆盖了整张表,mysql表示没有好的索引可以用,就显示这个【Range checked for each record】

在这里插入图片描述

3、Using filesort

这里的sql是根据字段进行分组,所以这里显示的 【Using filesort】 表示按照字段进行排序

(这个解释比较笼统,后续可以研究)

在这里插入图片描述

4、Using index

这是性能很高的一种情况。当查询所需的数据可以直接从索引树中检索到时就会显示【Using index】

在这里插入图片描述

在这里插入图片描述

5、Using temporary

查询的时候,Mysql需要创建一张临时表来处理该查询时会显示【Using temporary】

临时表是比较消耗资源的

在这里插入图片描述

6、Using where

当sql有where子句时,extra都会有说明。

但是这两个where字句,一个有显示 Using where ,一个没有,不太理解

在这里插入图片描述

7、Using union

一张表中有多个查询条件且都有索引时,会出现type类型为 index_merge ,进行索引合并类型,

Using union出现的场景 :

这里也一样,会使用union函数进行索引合并,跟type联接类型为 index_merge 一样

在这里插入图片描述

8、Using index for group-by

Using index for group-by 这个也可以理解为【索引覆盖】

索引覆盖:索引已经包括了我需要的字段了,就不用再通过索引去回表找主键索引来查询数据

分析图:

在这里插入图片描述
表明可以在索引中找到分组所需的所有数据,不需要查询实际的表。

在这里插入图片描述

覆盖索引的理解:

在这里插入图片描述

在这里插入图片描述

4)命令汇总:

在这里插入图片描述
在这里插入图片描述
按顺序:从上到下,性能最好的是 system , 性能最差的是 ALL

在这里插入图片描述

在这里插入图片描述

三、Join理解及优化

1、Inner join

谁是小表谁是大表,MySQL Optimizer会自动判断,和我们写表的顺序是无关的

在这里插入图片描述

2、join

join 和 inner join 一样的结果,谁是小表谁是大表,MySQL Optimizer会自动判断,和我们写表的顺序是无关的

在这里插入图片描述

3、where

where、join 和 inner join 一样的结果,谁是小表谁是大表,MySQL Optimizer会自动判断,和我们写表的顺序是无关的

在这里插入图片描述

4、left join

left join 就不用解释了,就是左表驱动右表,以左边的表为基准。

在这里插入图片描述

MySQL优化器要确定以谁为驱动表,也就是说以哪个表为基准,在处理此类问题时,MySQL

Optimizer采用了简单粗暴的解决方法:哪个表的结果集小,就以哪个表为驱动表.

5、straight_join

straight_join 是能优化sql性能的

STRAIGHT_JOIN 功能同 inner join 、 join 是一样的,区别只是能让左边的表来驱动右边的表,能改变 表优化器 对于 联表,其他的作用和 inner join 、 join 的效果都是一样的

在这里插入图片描述
这个是 dept_emp 为驱动表

在这里插入图片描述

因为 无论是 Inner join 还是 straight_join , 用 Explain 命令看的话,都是以 dept_emp 为驱动表,所以两者的耗时其实是差不多的。

在这里插入图片描述

因为这条sql语句 无论是用 inner join 还是 straight_join , 都是以 dept_emp 为驱动表,所以看不出使用 straight_join后的性能提升。

所以我用 straight_join 把employees 表弄成驱动表,那么结果应该就是 驱动表为 employees 的sql语句性能比较低。如图也能看出

注意: straight_join 是用来让左边的表作为驱动表的,跟left join 一样的作用,不过似乎使用 straight_join的性能会比使用 left join 的性能要高。

在这里插入图片描述

6、场景优化情况

优化情况:添加索引,或者是更改驱动表

在这里插入图片描述

优化情况:根据情况设置缓冲区大小

在这里插入图片描述

7、Show profiles:比较性能

Show profiles是MySql用来分析当前会话SQL语句执行的资源消耗情况,可以用于SQL的调优测量

在这里插入图片描述
在这里插入图片描述

四、一些索引测试

1、模糊查询like

用like做查询时,通配符% 放在字段值后面(样子为—>xxx%),进行前缀查询,索引就能使用,

前缀查询的样子abc%,就可以拿a、b、c先去索引树进行匹配,所以索引就可以使用。

如果把通配符%放在字段值最前面来进行后缀查询(样子为—>%xxx),那么索引就会失效。

比如后缀查询的样子是 【%abc】,我们根本不知道%是什么值,也就没办法在索引树进行比对,所以索引就会失效

在这里插入图片描述

2、范围查询

>、<

进行范围查询后,后续的查询条件的字段的索引就会失效 ,就不会再走索引

大于和小于 会导致后面的索引失效

在这里插入图片描述

between

between 不会导致后面索引失效

在这里插入图片描述

3、函数

使用函数会导致该字段的索引失效,如图

在这里插入图片描述

4、or & and

**使用or不会导致索引失效的情况:**就是or左右的查询条件的字段都有加索引(单值索引 或者 复合索引(复合索引要符合最左原则才行))

使用or导致索引失效的情况: or左右的查询条件的字段有一个以上没有加索引或者不满足索引规则,那么使用or就会导致索引失效

or 会导致索引失效的情况

在这里插入图片描述
如上图,如果想让 这个 or 不导致索引失效,我们可以单独给这个title 加上一个所以就可以了。

如图:

在这里插入图片描述

5、算数表达式

在该字段进行算数表达式也会导致索引失效

如图:
在这里插入图片描述

五、索引使用策略及优化

1、索引选择性

索引的选择性是指索引列中不同值的数目表中记录数的比

如果一个表中有2000条记录,表索引列有1980个不同的值,那么这个索引的选择性就是1980/2000=0.99。

比如有2000条数据,值记录的是男和女,那么这个表索引列就是有2个不同的值,索引选择性就是 2/2000,就是一千分之一,表明索引的效率很低。

如果是20000条数据,那么就是 2/20000 等于一万分之一

一个索引的选择性越接近于1,这个索引的效率就越高。

既然索引可以加快查询速度,那么是不是只要是查询语句需要,就建上索引?

答案是否定的。

因为索引虽然加快了查询速度,但索引也是有代价的:索引文件本身要消耗存储空间,同时索引会加重插入、删除和修改记录时的负担,另外,MySQL在运行时也要消耗资源维护索引,因此索引并不是越多越好。

情况1:如果表的记录比较少,少于2000条数据,那么就没必要建立索引。

情况2:超过2000条数据的表,也要看索引的选择性,索引的选择性太低也没必要建立索引。比如男和女这种。

除了选择性需要考量,这个索引的长度也要考量,因为索引的长度越长,那么需要消耗的空间就越多。

在这里插入图片描述

索引长度理解:

在这里插入图片描述

2、前缀索引

有一种与索引选择性有关的索引优化策略叫做前缀索引,就是用列的前缀代替整个列作为索引key,当前缀长度合适时,可以做到既使得前缀索引的选择性接近全列索引,同时因为索引key变短而减少了索引文件的大小和维护开销。

前缀索引分析:

需求: first_name 和 last_name 字段这些字段来查询数据。

1、根据两个字段查询数据,没有添加索引的情况下,耗时是0.068s

在这里插入图片描述
2、根据情况看是否要给字段建立单值索引,可通过计算出索引选择性的大小来看。

查看 first_name 和 last_name 字段的索引选择性,发现都太小,不适合建立单值索引。

在这里插入图片描述

3、复合索引

复合索引符合要求,索引选择性达到了0.9313,可以建立,但是可以看到两个字段的长度加起来是30,弄成符合索引之后,因为长度越长越消耗空间。

有没有兼顾长度和选择性的办法?

可以考虑用fifirst_name和last_name的前几个字符建立索引,例如<fifirst_name, left(last_name, 3)>,看看其选择性

在这里插入图片描述
4、优化复合索引,减少复合索引的长度

在这里插入图片描述

5、再对比下查询性能,速度提升了 278倍

在这里插入图片描述
6、注意点

前缀索引兼顾索引大小和查询速度,但是其缺点是不能用于ORDER BY和GROUP BY操作,也不能用于

Covering index(即当索引本身包含查询所需全部数据时,不再访问数据文件本身)

3、自增id作主键的原因

在使用InnoDB存储引擎时,如果没有特别的需要,请永远使用一个与业务无关的自增字段作为主键

为什么要用一个自增的id作为主键?

解释:

自增id:
涉及到磁盘的位置,因为如果输入的位置是连续的话,可以把一个位置用完之后,才会再去申请下一块位置,因为位置是连续的。

uuid:
因为不是连续的,所以存入的位置不会按顺序插入,可能这个位置插一个数据,另一个位置插入一个数据,可能导致的结果就是 一个位置还没用完,数据就会插到另一个位置。
这样会产生很多空间的碎片,就是一个区域还没用完,就会去重新申请新的一块区域,导致空间浪费。

比如行李箱,一件一件摆好的话,存的衣服会更多(自增id),如果随便丢进行李箱,那么能塞进去的衣服就会比较少(uuid),一些空间缝隙没利用到

为什么要用自增id作为主键的分析图

在这里插入图片描述

六、其他优化

1、order by 优化

order by 作用:对指定列进行排序

ORDER BY 实现原理:
1,通过有序索引而直接取得有序的数据;
2,通过MySQL 的排序算法将存储引擎中返回的数据进行排序然后再将排序后的数据返回;

双路排序:

顺序读性能比乱序读高

内存排完序之后,需要回表进行乱序读,查询需要的字段。

在这里插入图片描述

单路排序:

单路排序没有 row_id这个磁盘地址

因为 sortBuffer 是把表的整行数据都读过去的,所以在内存排完序的结果就是最终的结果,不用跟双路排序一样还得回表查。

单路排序速度比双路排序要快,不过比较占内存。

在这里插入图片描述

区别:

order by 怎么选择 单路排序还是双路排序?

MySQL根据设置的【max_length_for_sort_data】变量来确定走【单路排序】还是【双路排序】,默认值是1024字节,

如果需要返回的【列的总长度】(就是元组长度) 大于 【max_length_for_sort_data】,走【双路排序】,

否则走【单路排序】。

查看:show variables like ‘max_sort_length’;

在这里插入图片描述

单路排序算法:sort buffer 缓冲区缓存整个行的数据,在根据排序字段进行排序,返回数据给客户端,

缺点:占用内存

优点:避免回表查询

双路排序算法:sort buffer 缓冲区只缓存主键id和排序字段在内存中,在根据排序字段进行排序,在做一次回表查询,根据主键id查询该行数据返回给客户端。

区别1:

查询返回的字段如果比较多,那么 order by 就是走【双路排序】,

查询返回的字段如果比较少,那么 order by 就是走 【单路排序】。

区别2:

双路排序有值的磁盘物理地址,单路排序没有。

**元组:**双路排序的元组是 row_id(磁盘物理地址),单路排序的元组就是那些字段,所以单路排序的元组比双路排序的元组长

解释:

单路因为元组比较长,所以需要占的空间就比双路排序的多,在同样的内存大小的 Sortbuffer内存缓冲区 中,单路存的元组就比双路的少,所以产生的临时文件就会比双路的多。

但是双路排序有顺序读和乱序读,所以它的磁盘io次数是比单路排序的要多。

所以总的来说,单路排序的性能会比双路排序的性能会好些,但是还是得看情况而定

1)双路排序会读取两次表, 且第二次是随机读取的
2)单路排序的元组比双路排序要长,导致它需要多次向临时文件写入内容,增加IO操作,当需要返回的列的总长度很长时尤其明显。

提问:

问题:如果一次排序的顺序高达1万条,10万条的数据,能一次性加载到内存中吗?

答:

如果要排序的数据量太多的话,不可能一次性把数据都读取到内存,这样会把mysql的服务器的内存一下子就占满了。

MySQL会进行分批次的读取,比如有1万的数据,在内存可能会一次读1千,然后执行完得到最终结果后,会把排好序存储在一个临时文件中(1千条排序后的结果)。

然后再重复上面的操作,1万条数据,一次1千的分批读,那么就会产生10个临时文件,然后再针对这10个临时文件重新读取,然后在内存中进行归并排序,这个时候的性能肯定比直接一万条数据直接排序的性能更高。

数据量多的情况下,单路排序和双路排序都是这么分批次处理的。

优化:

ORDER BY 实现原理:
1,通过有序索引而直接取得有序的数据;
2,通过MySQL 的排序算法将存储引擎中返回的数据进行排序然后再将排序后的数据返回;

优化方案:
1,加大max_length_for_sort_data 参数

(加大这个参数,那么就提高比元组长度大的概率,所以就提高走单路排序的概率)

2,去掉不必要的返回字段

(不必要的返回字段越多,元组长度就越长,占的空间就越多,导致排序缓冲区每次读取的数据量变小)

3,增大sort_buffer_size (排序缓冲区)参数,

(增大的话,排序缓冲区一次性能读取的数据就会变多)

增大 sort_buffer_size 和 max_length_for_sort_data 参数,尽量走单路排序,减少临时文件产生,减少IO,尽量避免走双路排序。

2、using temporary

http://mysql.taobao.org/monthly/2015/03/04/

3、group by 优化

分组

GROUP BY的前提是排序,所以优化手段和ORDER BY是一样的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/164096.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MSQL系列(六) Mysql实战-SQL语句优化

Mysql实战-SQL语句优化 前面我们讲解了索引的存储结构&#xff0c;BTree的索引结构&#xff0c;以及索引最左侧匹配原则&#xff0c;Explain的用法&#xff0c;可以看到是否使用了索引&#xff0c;今天我们讲解一下SQL语句的优化及如何优化 文章目录 Mysql实战-SQL语句优化1.…

【Docker】Docker网络及容器间通信详解

目录 背景 默认网络 1、bridge 网络模式 2、host 网络模式 3、none 网络模式 4、container 网络模式 自定义网络 容器间网络通信 IP通信 Docker DNS server Joined容器 前言 本实验通过docker DNS server和joined 容器两种方法实现Docker容器间的通信。Docker容器间…

hue实现对hiveserver2 的负载均衡

如果你使用的是CDH集群那就很是方便的 在Cloudera Manager中&#xff0c;进入HDFS Service 进入Instances标签页面&#xff0c;点击Add Role Instances按钮&#xff0c;如下图所示 点击Continue按钮&#xff0c;如下图所示 返回Instances页面&#xff0c;选择HttpFS角色…

新加坡服务器托管

新加坡是一个小而繁荣的国家&#xff0c;是东南亚唯一一个发达国家。它地理位置好&#xff0c;毗邻马来西亚和印度尼西亚&#xff0c;新加坡是一个拥有先进科技和强大经济的国家&#xff0c;主要以制造业、金融、旅游和航运为主&#xff0c;拥有先进的经济和现代化的基础设施&a…

Python入门指南

概述&#xff1a; Python是一种简单易学、功能强大的编程语言&#xff0c;广泛应用于数据分析、Web开发、人工智能等领域。本文将为初学者提供一个Python入门指南&#xff0c;从安装到基本语法&#xff0c;帮助您开始编写Python程序。 第一部分&#xff1a;安装Python 1、进入…

C++ 友元

采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数…

DC电源模块的模拟电源对比数字电源的优势有哪些?

BOSHIDA DC电源模块的模拟电源对比数字电源的优势有哪些&#xff1f; DC电源模块是一种电子元件&#xff0c;用于将交流电转换为直流电&#xff0c;以供电路板、集成电路等电子设备使用。在直流电源模块中&#xff0c;有模拟电源和数字电源两种类型。 模拟电源是一种传统的电源…

移动硬盘被格式化了如何恢复数据?四步教你如何恢复

在日常生活中&#xff0c;我们常常会使用各种存储设备来保存和备份我们的重要数据。移动硬盘作为一种便携式的存储设备&#xff0c;被广泛应用于数据的存储和传输。然而&#xff0c;有时候我们会不小心将移动硬盘格式化&#xff0c;从而丢失了里面的数据。本文将介绍移动硬盘格…

【SA8295P 源码分析 (三)】97 - QNX AIS Camera 框架介绍 及 Camera 工作流程分析

【SA8295P 源码分析】97 - QNX AIS Camera 框架介绍 及 Camera 工作流程分析 一、QNX AIS Server 框架分析二、QNX Hypervisor / Android GVM 方案介绍三、Camera APP 调用流程分析四、QCarCam 状态转换过程介绍五、Camera 加串-解串 硬件链路分析六、摄像头初始化检测过程介绍…

基于MATLAB的图像条形码识别系统(matlab毕毕业设计2)

摘要 &#xff1a; 本论文旨在介绍一种基于MATLAB的图像条形码识别系统。该系统利用计算机视觉技术和图像处理算法&#xff0c;实现对不同类型的条形码进行准确识别。本文将详细介绍系统学习的流程&#xff0c;并提供详细教案&#xff0c;以帮助读者理解和实施该系统。 引言…

软件项目管理【UML-组件图】

目录 一、组件图概念 二、组件图包含的元素 1.组件&#xff08;Component&#xff09;->构件 2.接口&#xff08;Interface&#xff09; 3.外部接口——端口 4.连接器&#xff08;Connector&#xff09;——连接件 4.关系 5.组件图表示方法 三、例子 一、组件图概念…

LVS+Keepalived 实验

Keepalived 是什么 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案&#xff0c;可以解决静态路由出现的单点故障问题的一款检查工具 在一个LVS服务集群中通常有主服务器&#xff08;MASTER&#xff09;和备份服务器&#xff08;BACKUP&#xff09;两种角色的服务器…

Vue笔记_插件组件_lucky-canvas抽奖转盘

文章目录 官网使用(vue2.x)[1] 下载[2] 引入[3] 使用配置项-width/height配置项-blocks配置项-prizes配置项-buttons优化案例 lucky-canvas 是一个基于 Js Canvas 的抽奖 web 前端组件&#xff0c;提供 大转盘和 九宫格两种抽奖界面&#xff0c;UI 精美&#xff0c;功能强大…

2020年12月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python编程&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 要对二维列表所有的数据进行格式化输出&#xff0c;打印成表格形状&#xff0c;程序段如下&#xff1a; ls [[金京,89],[…

通达OA通用版V12的表单js定制开发,良好实践总结-持续更新

通达OA通用版V12的表单js定制开发的良好实践总结-持续更新 良好实践总结在表单中的js区域标准代码2023年10月19日获取地址栏&#xff1a;协议、域名/IP地址端口号获取地址栏的参数&#xff0c;比如run_id、flow_id等向表单中追加自定义css、js文件 良好实践总结 在webroot下的…

vue3学习(十)--- 依赖注入Provide 和 Inject

文章目录 Provide 和 Inject兄弟组件通信Event BusMitt库 Provide 和 Inject provide 可以在祖先组件中指定我们想要提供给后代组件----子、孙等组件的数据或方法&#xff0c;而在任何后代组件中&#xff0c;我们都可以使用 inject 来接收 provide 提供的数据或方法。 父组件…

如何通过沉浸式投影技术提升文旅夜游的互动体验?

伴随着国民经济的提升&#xff0c;文旅夜游市场也开始通过各类创新设计形式&#xff0c;来吸引更多的游客前来打卡游玩&#xff0c;使其逐渐成为了当下热度较高的一种游玩模式&#xff0c;其中在收集各类用户的体验反馈时&#xff0c;沉浸式投影依靠新颖的视觉体验以及沉浸式观…

SpringCloud-Sentinel

一、介绍 &#xff08;1&#xff09;提供界面配置配置服务限流、服务降级、服务熔断 &#xff08;2&#xff09;SentinelResource的blockHandler只处理后台配置的异常&#xff0c;运行时异常fallBack处理&#xff0c;且资源名为value时才生效&#xff0c;走兜底方法 二、安装…

android 指针动画转动

记录一种简单动画 效果图&#xff1a; 都是直接使用图片资源FrameLayout布局实现&#xff0c;布局如下&#xff1a; <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto"…

python小游戏:飞机射击游戏代码

创建一个完整的飞行游戏涉及到许多方面&#xff0c;包括图形设计、游戏物理引擎和用户输入处理等。在这里&#xff0c;我将提供一个简单的基础框架&#xff0c;你可以在其基础上进一步扩展和完善游戏。 在这个示例中&#xff0c;我们将使用Pygame库来创建一个基本的飞行游戏。…