当前位置: 首页 > news >正文

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是一样的。

相关文章:

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

目录 一、影响性能的相关因素存储过程&#xff1a; 二、sql优化1>、Mysql系统架构2>、引擎区别&#xff1a; 3>、索引1、什么是索引&#xff1f;联合主键索引理解&#xff1a;索引长度理解&#xff1a;什么是慢查询&#xff1f; 1&#xff09;、索引理解2&#xff09;…...

Flutter - APP跳转高德、百度、腾讯、谷歌地图

demo 地址: https://github.com/iotjin/jh_flutter_demo 代码不定时更新&#xff0c;请前往github查看最新代码 这里介绍的是不需要自己开发地图&#xff0c;直接通过给定的经纬度&#xff0c;跳转到三方地图APP调用导航的方式 一种是写的工具类&#xff0c;一种是通过调用三方…...

Flyway Desktop updated

Flyway Desktop updated 为比较工件序列化和反序列化添加了额外的调试日志记录。 Flyway Desktop现在将记住以前用于创建项目和匹配克隆的位置。 新的脱机许可工作流现在已在Microsoft Windows上启用。 现在&#xff0c;在配置目标数据库列表时&#xff0c;环境ID是可见的。 现…...

阿里云短信服务设置操作项目

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

学习笔记|串口通信实战|简易串口控制器|sprintf函数|STC32G单片机视频开发教程(冲哥)|第二十一集(下):串口与PC通信

目录 3.串口通信实战实操简易的工作原理Tips:sprintf函数简介 总结课后练习 3.串口通信实战 做一个简易串口控制器。发送对应指令&#xff0c;让板子做相应的事情&#xff0c;或者传输数据&#xff08;文本模式下发送&#xff0c;不要选择HEX&#xff09;。 1.串口发送字符Ax\…...

卷积神经网络CNN学习笔记-卷积计算Conv2D函数的理解

目录 1.全连接层存在的问题2.卷积运算3.填充(padding)3.1填充(padding)的意义 4.步幅(stride)5.三维数据的卷积运算6.结合方块思考7.批处理8.Conv2D函数解析9.conv2d代码9.1 stride19.2 stride2 参考文章 1.全连接层存在的问题 在全连接层中&#xff0c;相邻层的神经元全部连接…...

收藏,安装报错信息汇总,MacOS上安装Adobe等软件/插件报错问题解决合集

打开允许“允许任何来源” 如何打开允许任何来源&#xff1f;在 Finder 菜单栏选择 【前往】 – 【实用工具 】&#xff0c;找到【终端】程序&#xff0c;双击打开&#xff0c;在终端窗口中输入&#xff1a;sudo spctl --master-disable 输入代码后&#xff0c;按【return 回车…...

Qt 报错:munmap_chunk(): invalid pointer解决方案

问题 在用Qt写程序的时候。报了munmap_chunk(): invalid pointer这个错误消息。 造成原因 在 Qt 程序中&#xff0c;这种错误可能出现在多种情况下&#xff0c;以下几点是容易造成此问题的原因&#xff1a; 函数未实现返回值&#xff1a;函数有返回值&#xff0c;但函数体中…...

【Java题】实现继承和多态的例子

一&#xff1a;题目 1.员工类Employee&#xff1a; &#xff08;1&#xff09;私有成员变量&#xff1a;姓名&#xff0c;年龄&#xff0c;工资 &#xff08;2&#xff09;提供无参&#xff0c;有参构造 &#xff08;3&#xff09;成员方法&#xff1a;work()方法——员工工作 …...

‘conda‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

原因&#xff1a;环境变量没有正确添加解决&#xff1a;我的电脑—右键属性—高级系统设置—环境变量—系统变量—Path—双击进入—新建&#xff0c;去安装Anaconda的目录下&#xff0c;找到Library中的bin&#xff0c;将此时的路径粘贴到此处...

C1N短网址 - 是如何做到行业领先的

今天从技术角度来聊下短网址的一些事情&#xff0c;市面上的短网址发展基本上经历了几个阶段。 短网址发展的几个阶段&#xff1a; 第一阶段&#xff1a;网址缩短&#xff0c;很纯粹的功能&#xff0c;各个大小公司都在做&#xff0c;门槛很低。典型代表&#xff1a;百度短网…...

【UE5】引入C++插件Plugins不在UE里出现

原因 未编译过C 原项目为蓝图项目&#xff0c;或者虽然为C项目&#xff0c;但并为编译过C. 解决 创建一个C脚本&#xff0c;让编辑器重启重新编译一遍。 如还不行&#xff0c;则打开Plugins插件面板&#xff0c;创建一个空的新的插件&#xff0c;再让引擎自动重启重新编译…...

第三部分:JavaScript

一&#xff1a;JavaScript介绍 JavaScript语言诞生主要是完成页面的数据验证。因此它运行在客户端&#xff0c;需要运行浏览器来解析执行JavaScript代码。 JavaScript是Net scape网景公司的产品&#xff0c;最早取名为LiveScript&#xff1b;为了吸引更多的程序员&#xff0c;更…...

Redis 命令—— 超详细操作演示!!!

内存数据库 Redis7 三、Redis 命令3.1 Redis 基本命令3.2 Key 操作命令3.3 String 型 Value 操作命令3.4 Hash 型 Value 操作命令3.5 List 型 Value 操作命令3.6 Set 型 Value 操作命令3.7 有序Set 型 Value 操作命令3.8 benchmark 测试工具3.9 简单动态字符串SDS3.10 集合的底…...

工业自动化控制通信协议Profinet系列-3、CoDeSys软PLC方案介绍

工业自动化控制通信协议Profinet系列-3、CoDeSys软PLC方案介绍 文章目录 工业自动化控制通信协议Profinet系列-3、CoDeSys软PLC方案介绍一、前言二、Profinet搭建资料收集三、CoDeSys系列四、接下来 一、前言 之前在树莓派desktop上已经成功编译运行测试程序&#xff0c;但是还…...

[补题记录] Atcoder Beginner Contest 293(E)

URL&#xff1a;https://atcoder.jp/contests/abc293 目录 E Problem/题意 Thought/思路 Code/代码 E Problem/题意 给出 A、X、M&#xff0c;求 。 Thought/思路 一开始想等比数列求和&#xff0c;但是 m 不保证是质数&#xff0c;所以不能用。 假设 dp[x] 表示&…...

R语言有关模型方面的函数(model.)介绍-model.matrix

R语言有关模型方面的函数(model.)介绍-model.matrix 引言model.matrix简单作用提取设计矩阵对有序因子与无序因子的处理(模型相关)手动编写contr.系列的函数写在最后引言 最近闲暇时间大量阅读了一些机器学习方面的R包源码,在此对阅读过程中的一些实用但是不常见的函数进行…...

owasp top 10

1、访问控制的崩溃&#xff1a; 通过身份验证的用户可以访问其他用户的信息&#xff0c;越权 达成方式&#xff1a;通过修改url、内部应用程序状态或html页面绕过 防范&#xff1a;除了公有资源外&#xff0c;默认情况下拒绝访问&#xff0c;严格判断权限&#xff0c;记录失败的…...

【FreeRTOS】【STM32】06 FreeRTOS的使用-动态创建多任务 FreeRTOS 的启动流程

主要流程参照【FreeRTOS】【STM32】06 FreeRTOS的使用-动态创建单任务 1.定义任务句柄 static TaskHandle_t AppTaskCreate_Handle NULL;2.硬件初始化 略 3.创建具体功能任务函数 见定义任务函数 4.使用xTaskCreate创建任务 xReturn xTaskCreate((TaskFunction_t )AppT…...

10月21日,每日信息差

今天是2023年10月21日&#xff0c;以下是为您准备的13条信息差 第一、东方物探公司与阿里云达成战略合作&#xff0c;逐步助力勘探行业实现智能化、自动化、绿色化和可持续化的目标 第二、九洲集团签约300MW集中式风电项目计划总投资21亿&#xff0c;项目达产后&#xff0c;预…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...

JS红宝书笔记 - 3.3 变量

要定义变量&#xff0c;可以使用var操作符&#xff0c;后跟变量名 ES实现变量初始化&#xff0c;因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符&#xff0c;可以创建一个全局变量 如果需要定义…...

DAY 45 超大力王爱学Python

来自超大力王的友情提示&#xff1a;在用tensordoard的时候一定一定要用绝对位置&#xff0c;例如&#xff1a;tensorboard --logdir"D:\代码\archive (1)\runs\cifar10_mlp_experiment_2" 不然读取不了数据 知识点回顾&#xff1a; tensorboard的发展历史和原理tens…...

Yii2项目自动向GitLab上报Bug

Yii2 项目自动上报Bug 原理 yii2在程序报错时, 会执行指定action, 通过重写ErrorAction, 实现Bug自动提交至GitLab的issue 步骤 配置SiteController中的actions方法 public function actions(){return [error > [class > app\helpers\web\ErrorAction,],];}重写Error…...