mysql

mysql架构图

Innodb架构图

索引

索引是帮助Mysql高效获取数据的排好序数据结构

索引数据结构

  • 二叉树

    极限情况单边树,不平衡

  • 红黑树

    自平衡,但是数据量大的时候深度也很大(1-2-4-8-16-2的n次幂)

  • hash表

    hash之后直接找到磁盘文件指针,虽然很快,但是搞不定范围查找这个情景

    相当于redis,可以处理下不会变动的历史数据场景

  • b-tree树

为什么不把索引数据存储在一个节点里面?(说的是主键索引)

java-cpu-ram(内存)===硬盘,先从内存拿,取不到从硬盘拿,硬盘和内存的最小单位是叶(4kb),交互只能是叶的整数倍

磁盘拿数据到内存,最小的交互单位是4kb,一次最多拿几十k的数据,因为太大的话计算机底层不支持,所以不可能把索引都放在一个节点里面。

查看mysql叶节点存储数据的大小,show global status like ‘Innodb page size’;查询结果是16384byte=16Kb,叶节点就是下图中的每一行(15+56+77)

为什么要设置成16kb?

innodb

mysaim

主键是bigint,占用8byte,索引的子节点(和索引成对出现的磁盘文件指针)占用6byte(15旁边的空格就是磁盘文件指针),也就是说一个叶节点可以存储16384byte / (6byte+8byte) ==1170个索引数据

mysaim引擎叶子节点的data数据放的是索引所在行的磁盘文件指针

innodb引擎叶子节点的data数据放的是索引索引所在行的其他所有字段

mysql一般把根节点(15+56+77)放到内存,而不是从磁盘查找,之后才在磁盘查找

联合索引底层数据结构(字典)

指针是双向的!!!!

先比较第一列,整型,之后比较字符串(ASCII码),之后date

如果三个字段是联合主键,下面的data是其他字段

如果三个字段是普通索引,下面的data是主键

图示代表a,ab,abc ,ac(只用a的索引,索引比较先比较第一个,之后第二个,之后第三个,不能从一跳到三)

例如 a=1 and b>1 and c=1 走ab索引,因为必须先找到 a=1 and b>1的所有记录,想就相当于这个条件的所有数据了(范围右边索引列失效,但是范围当前位置的索引是有效的)(btree是节点比较必须是等于)

结合数据结构,不等于肯定是不走索引的 ,like ‘%wu’肯定不走,like’wu%’走(*的话不会走索引,可以试试覆盖索引)

实例:abcd是联合索引(mysql内部优化,之后也可以看explain查看,关注key_len和ref)select * from A

a=1 and b=1 and c=1 and d=1(走4个索引)

a=1 and c=1 and b=1 and d=1(走4个索引)

a=1 and d=1 and c=1 and b=1(走4个索引)

d=1 and c=1 and b=1 and a=1(走4个索引)

a=1 and b=1 and d>1 and c=1(走4个索引)

a=1 and b=1 and d=1 and c>1(走3个索引)

a>1 and b=1 and c=1 and d=1(不走索引,全表扫描,有可能值在联合索引里面没有1这个节点,没办法先根据a=1找之后走链表 )(用覆盖索引)

a>=1 and b=1 and c=1 and d=1(不走索引,全表扫描)

a=1 and b=1 and d=1 order by c asc(desc使用索引情况一样,底层数据结构双向指针)(c走索引,虽然key_len里面显示只用了两个索引,但是extra里面没有file sort,所以代表c是走索引的)

a=1 and b=1 order by d(d不走索引,extra里面有filesort)

a=1 and d=1 order by b,c(排序时b,c走索引了,extra里面没有filesort)

磁盘存取原理

企业微信截图_46597d5b-2b59-4707-bdcf-4c474024553e.png

存储引擎

针对的是表,不是库

数据存储的磁盘位置,/var/lib/mysql/,先是库,后是表

frm文件存储的是表结构的定义

ibd文件存储的是 b+tree和数据的一个汇总文件

执行计划explain

type列:表示关联类型或访问类型,即myssql决定如何查找表中的行

最优到最差

system(表就一条记录)

const(唯一索引,结果集就一个记录)

eq_ref(关联的字段是主键索引或者唯一索引)

ref(关联的字段不是主键或者唯一索引)

range(范围查询)

index(扫描全表索引,从索引里面读取)

all(从硬盘读写,查询字段不全是索引)

extra列(具体见文档)(覆盖索引?索引前导列?优化成using index)

using index(查询的列被索引覆盖,并且where筛选条件是索引的前导列)

using where using index (查询的列被索引覆盖,并且where筛选条件是索引列之一,但是不是索引的前导列,也就是无法通过索引来查找到符合条件的数据)

using where(查询的列未被索引覆盖,并且where筛选条件不是索引的前导列)

null(查询的列未被索引覆盖,并且where筛选条件是索引的前导列)

using temporary(临时表 distinct,group by等场景会导致,查询的列未被索引覆盖)

using filesort(查询的列未被索引覆盖,如果被索引覆盖,不需要再排序是因为b-tree+提前排好了 )

key_len列和ref列

当ref为空时,不一定没有走索引,看key_len的索引位置的计算

当key_len为空,肯定没有用索引

索引类型

1.聚集索引(一般是主键):索引和数据聚集在一起了,叶子节点的data数据,根据条件查找到数据就能知道别的字段是什么值而mysaim通过数据找到磁盘文件指针,再在另外一个文件里面找别的字段的值,这样的就是非聚集索引

2.非聚集索引:索引上只包含被建立索引的数据,以及一个行定位符,这个行定位符,可以理解为一个聚集索引物理排序的指针,通过这个指针,可以找到行数据

3.覆盖索引:被查询的所有列都是索引,这时不用通过行定位符再到row上获取

Innodb为什么需要主键,为什么要自增的整型(聚集索引)

innodb数据文件必须有一个主键索引来帮我们组织数据结构,设计如此(上图)

如果不是自增的话,b+tree叶子节点是递增的,如果不是自增的整型会导致树进行分裂,平衡之后移动,耗费资源

innodb自增主键会把数据自动向后插入,避免了插入过程中的聚集索引的排序问题,聚集索引的排序,必然会带来大范围的数据的物理移动,带来磁盘io的性能损耗,如果聚集索引的值可以改变的话,那么也会发出物理磁盘上的移动,于是就可能出现磁盘页分裂(索引存储在磁盘上!!!),表碎片横生

不要创建过多的索引:

1.创建和维护索引要耗费时间,这种时间随着数据量的增加而增加; 2.创建索引占空屋里空间,聚簇索引占用空间更大; 3.对表中的数据进行增删改,索引也要动态维护

索引的数据结构 - B-树

1.索引为什么要树结构存储

树的查询效率高,而且有序

2.为什么没有用二叉树呢

二叉树时间复杂度O(logN),从算法逻辑来讲,查找速度和比较次数都是最小的,但是磁盘IO问题,数据库的索引存储在磁盘上,当数据量很大的时候,索引几个G,不可能把整个索引全部加载到内存,能做的只是逐一加载每一个磁盘页,这里的磁盘页对应索引树的节点。

二叉树的查找,4次磁盘IO,找到元素10

为了减少磁盘IO,我们需要把瘦高的树,变的矮胖,这就是B-树的特征之一。

3.B-树

多路平衡查找树,它的每个节点最多包含k个孩子,k被称为B树的阶,k的大小取决于磁盘页的大小。

特征:

1.根节点最少两个子女

2.每个中间节点都包含k-1个元素和k个孩子,m/2<=k<=m

3.每个叶子节点都包含k-1个元素,m/2<=k<=m

4.所有的叶子节点位于同一层

5.每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的至于分划

在内存中定位,比较3,5,相比于磁盘IO的速度,内存耗时可以忽略不计

4.B-树的卫星数据

5.B-树的新增 - 自平衡

6.B-树的删除

Mysql索引数据结构

B+树是基于B-树的一种变体,有着比B-树更高的查询性能

B+树的特征

1.k阶b+树,中间节点包含k个元素(B-树是k-1个元素),每个元素不保存数据,只用来记录索引,所有数据都保存在叶子节点

2.所有叶子节点包含了全部的元素信息,及指向含这些元素记录的指针,且叶子节点本身依关键字的大小自小而大顺序连接

3.所有中间节点元素都同时存在于子节点,在子节点元素中是最大或最小元素

叶子节点形成了一个有序链表

B+树的卫星数据

卫星数据指的是索引元素指向的数据记录,比如数据库中的某一行

在数据库的聚集索引中,叶子节点直接包含卫星数据,在非聚集索引中,叶子节点带有指向卫星数据的指针

B+树查询性能(单行查询 + 范围查询)之三个优势

在B+树中单行查询找3这个元素和B-树的不同体现在

1.B+树中间节点没有卫星数据,相同大小的磁盘页可以容纳更多的节点元素,IO次数更少

2.B+树查询必须找到叶子节点查询性能稳定

在B+树中范围查询找3到11的元素和B-树的不同体现在

1.B-树只能采用中序遍历的方法,B+树只需要在链表上做遍历即可

存储引擎

MyISAM表锁(偏读);Innodb行锁,事务(偏写)

MyISAM读锁(应用范围:数据迁移):当前session和其他session都可以读该表,当前session中插入和更新锁定的表都会报错,其他session插入或更新则会等待

MyISAM写锁:当前session可以进行读写,其他session进行读写会等待

MyISAM在执行查询语句(select)前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的表加写锁

Innodb行锁:开启事务,session1更新某一行,session2更新同一行被阻塞,但是更新其他行正常

事务ACID

原子性Atomicity:事务是一个原子操作,对数据的修改要么全成功,要么全失败

一致性Consistent:在事务开始和完成时,数据都必须保持一致状态。意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;事务结束时,所有的内部数据结构(b树索引和双向链表)也都必须是正确的。[一个事务单元需要提交之后才会被其他事务可见]

隔离性Isolation:数据库提供一定的隔离机制,保证事务在不受外部并发操作影响的独立环境执行,意味着事务处理过程中的中间状态对外部是不可见的

持久性Durable:事务完成后,他对数据的修改是永久性的,即使出现系统故障也能保持

并发事务处理带来的问题

  • 脏读,不可重复读,幻读都是一个事务写,一个事务读引起的情况
  • 丢失更新是两个事务一起写引起的另外一个场景

更新丢失: 第二个事务覆盖第一个事务的值,用乐观锁解决 where version=?,version是操作之前查询出来的值

脏读:事务A读取到事务B已经修改但尚未提交的数据,还在这个数据基础上做了操作,此时如果B事务回滚,A读取的数据无效,不符合一致性要求

不可重复读:事务A读取到事务B已经提交的修改数据,不符合隔离性(【事务A一直都没有提交】事务A先读了一次,事务B对数据进行修改,没有提交的时候,事务A读不到,没有脏读,事务B提交了,事务A就可以读到了,两次事务A读到的数据不一致,不符合隔离性)

幻读: 事务A读取到了事务B提交的新增数据,不符合隔离性(【事务A一直都没有提交】事务A查结果350,事务B变成了300并且提交了,事务A再查350,解决了不可重复读,事务B新增了一个数据,事务A查询不到,事务A做了一个修改的操作或者新增的操作,事务B对数据库的更改,事务A就可以看见了(mvcc机制),不符合隔离性)

可重复读使用了MVCC机制,select不会更新版本号,是快照读(历史版本),insert,update和delete会更新版本号,是当前读(当前版本),例如:事务A一直都没有提交,事务A查结果350,事务B变成了300并且提交了,事务A执行了update操作减50,事务A再查询250

读已提交和可重复读的原理
  • 读已提交:每次读都创建一个快照(3在读的时候创建一个快照(记录此时活跃事务是2,3);此时查询undo log,发现最新版本的数据对应的事务是2,在快照里,找undo log上一个版本,发现不在快照里,可以读)
  • 可重复:只在第一次读的时候创建一个快照

脏读是事务B里面修改了数据

幻读是事务B里面新增了数据

人们在讨论隔离级别的时候,往往会说这个隔离级别的加锁方式是什么样子的。其实锁只是实现隔离级别的几种方式之一,除了锁,实现并发问题的方式还有时间戳,多版本控制等等,这些也可以称为无锁的并发控制

传统的隔离级别是基于锁实现的,这种方式叫做基于锁的并发控制(Lock-Based Concurrent Control,简写 LBCC)

通过对读写操作加不同的锁,以及释放锁的时机进行不同的控制,就可以实现四种隔离级别。

传统的锁有两种:读操作通常加共享锁(Share locks,S锁,又叫读锁),写操作加排它锁(Exclusive locks,X锁,又叫写锁);加了共享锁的记录,其他事务也可以读,但不能写;加了排它锁的记录,其他事务既不能读,也不能写。另外,对于锁的粒度,又分为行锁和表锁,行锁只锁某行记录,对其他行的操作不受影响,表锁会锁住整张表,所有对这个表的操作都受影响。

MVCC版本链:https://juejin.im/post/5da8493ae51d4524b25add55

归纳起来,四种隔离级别的加锁策略如下:

  • 读未提交(Read Uncommitted):事务读不阻塞其他事务读和写,事务写阻塞其他事务写但不阻塞读;通过对写操作加 “持续X锁”,对读操作不加锁 实现
  • 读已提交(Read Committed):事务读不会阻塞其他事务读和写,事务写会阻塞其他事务读和写;通过对写操作加 “持续X锁”,对读操作加 “临时S锁” 实现;不会出现脏读;
  • 可重复读(Repeatable Read):事务读会阻塞其他事务事务写但不阻塞读,事务写会阻塞其他事务读和写;通过对写操作加 “持续X锁”,对读操作加 “持续S锁” 实现;
  • 序列化(Serializable):为了解决幻读问题,行级锁做不到,需使用表级锁。

Mysql事物的隔离级别

mysql默认的隔离级别是可重复读

查询隔离级别:show variables like ‘tx_isolation’

修改数据库的隔离级别:set tx_isolation=’REPEATABLE-READ’

spring可以设置事务隔离级别,mysql也可以设置事务隔离级别,以spring为主

串行化:强制事物排序,使之不可能存在相互冲突,事物1没有提交之前,不允许事物2更改数据

如何防止幻读 - 间隙锁

根据检索条件向左,向右查询最靠近检索条件的记录值A,B,间隙锁区间为(A,B)

主要通过两个方面来实现防止幻读

1.防止间隙内有新数据被插入

2.防止已经存在的数据,更改成间隙内的数据

Innodb下的锁

1.共享锁(读锁),排它锁(写锁)(都是悲观锁)

​ 共享锁也叫读锁(SELECT … LOCK IN SHARE MODE;)

​ 排它锁也叫写锁(SELECT … FOR UPDATE;)

​ 即一个事物在读取一个数据行的时候,其他事物也可以读,但不能对该数据行进行增删改

​ 即一个事物对该数据行进行增删改的时候,其他事物不能读也不能改

2.记录锁(行锁),间隙锁(gap锁),next-key锁(记录锁+间隙锁)(全都属于排它锁)

​ innodb默认的加锁方式是next-key锁

3.悲观锁,乐观锁

​ 悲观锁:当事物A对某行数据应用了锁,并且这个事物把锁释放后,其他事物才能执行与该锁冲突的操作。

​ 乐观锁:在提交数据更新之前,每个事物都会检查在该事物读取数据后没有没有其他事物又修改了数据,如果其他事物又更新的话,那么当前正在提交的事物回滚。

在innodb下,加锁之前,为什么要先start transaction?

innodb下事物一旦提交或者回滚,就会自动释放事物中的锁,innodb的情况下autocommit=1即开启自动提交,在自动提交模式下,每执行一句sql,就自动提交事物,锁也会立即释放,所以我们在进行锁操作之前,会关闭自动模式开启手动模式

主从同步

0.当slave连接到master的时候,master会为slave开启binlog dump线程 1.master数据发生变更,该事件(insert,update,delete)会被按照顺序写到binlog,binlog dump线程会通知slave,并将相应的binlog内容发给slave 2.此时slave机器会创建两个线程 IO线程:接收binlog内容,将内容写到relay log中 SQL线程:读取relay log,根据relay log的内容对slave数据库进行修改 3.Mysql支持复制类型 语句复制:mysql默认采用语句复制,效率高 行复制:没法精确复制时,采用行复制,把主库行数据,直接复制到从库 混合复制:语句和行复制的混合

4.主从复制流程图

5.原理:WAL(write ahead logging)(事务提交时,保证将事务产生的日志先刷到磁盘,若事务更新失败,则可以通过日志回滚)

主从的强一致是通过WAL保证的,即先保证从库的relay log中继日志更新落盘比主库返回给应用程序事务已提交早

  • 主库事务提交的时候,发起两个操作,操作一是将日志写到本地磁盘,操作二是将日志同步到从库病确保落盘
  • 主库等待两个操作都成功返回之后,才返给应用程序,事务提交成功
  • 当有多个从库,为了提升性能,只要有一个从库返回日志落盘成功,主库日志已落盘的情况下,我们即返回应用查程序提交成功

6.主从复制控制台图

死锁检测

死锁日志:deadlock

死锁超时:当查询的时间达到所等待超时的设定后放弃锁请求(innodb_lock_wait_timeout),将持有最少行级排它锁的事物回滚

mysql打满问题分析

是不是有慢sql,分析数据库有多少个线程数,如果线程数都被慢sql占用了,数据库cpu就会被打满,但是如果sql瞬间执行完成,就不会有这个问题

mysql如何保证ACID

从数据库层面,数据库通过原子性、隔离性、持久性来保证一致性。也就是说ACID四大特性之中,C(一致性)是目的,A(原子性)、I(隔离性)、D(持久性)是手段,是为了保证一致性,数据库提供的手段。数据库必须要实现AID三大特性,才有可能实现一致性。

  • 原子性

    • 利用Innodb的undo logundo log名为回滚日志,是实现原子性的关键,当事务回滚时能够撤销所有已经成功执行的sql语句,他需要记录你要回滚的相应日志信息。
  • 持久性

    • 利用Innodb的redo log(重做日志)。正如之前说的,Mysql是先把磁盘上的数据加载到内存中,在内存中对数据进行修改,再刷回磁盘上。如果此时突然宕机,内存中的数据就会丢失。

    • redo log进行刷盘比对数据页刷盘效率高,具体表现如下

        • redo log体积小,毕竟只记录了哪一页修改了啥,因此体积小,刷盘快。
        • redo log是一直往末尾进行追加,属于顺序IO。效率显然比随机IO来的快。
  • 隔离性

    • 利用的是锁和MVCC机制。MVCC,即多版本并发控制(Multi Version Concurrency Control),一个行记录数据有多个版本对快照数据,这些快照数据在undo log中。 如果一个事务读取的行正在做DELELE或者UPDATE操作,读取操作不会等行上的锁释放,而是读取该行的快照版本。

update的流程

update之前先把数据从数据库查询出来,mysql的基本存储结构是页(记录都在页里面),所以mysql是先把这条记录所在的页找到,把该页加载到内存中,讲对应记录进行修改。

抛砖引玉:在内存中把数据改了,还没有来得及落盘,而此时的数据库挂了怎么办?

同步落盘,性能低,不可取

异步落盘,引入redo log(InnoDB引擎独有),先写内存再写redo log。内存对应的是buffer pool,是一个以页为元素的链表(为什么是链表呢,因为和缓存一样,需要一套淘汰策略来管理数据:LRU),redo log记载着这次在某个页上做了什么修改。

change buffer:如果内存中没有对应的页数据,mysql会把数据从磁盘load出来,如果每次页都不同或者不是相邻的页,每次都去load会很慢,于是mysql发现你要修改的页不在内存里面,就把你要对页的修改,记到一个叫change buffer的地方,同时记录redo log,然后再把数据load到你内存,load过来后,再把change buffer里记录的修改,应用到内存(buffer pool)中,这个动作叫merge,再把内存数据刷到磁盘的动作叫purge。

change buffer只操作二级索引时才使用,原因是聚簇索引是唯一的,也就意味着每次插入更新都需要检查是否存在相同的字段,没有必要change buffer了。

mysql索引不管是在磁盘还是内存,都是B+树,每次的查询次数取决于树的深度,数据就算已经放到内存了还不能一下子找到他,这样空间牺牲很大,尤其是频繁访问的数据,每次都要走B+树,可以直接用一个指针把数据的位置记下来,这就是自适应哈希索引,自适应的意思是mysql会自动评估使用自适应索引是否值得,如果更快就建立。

log buffer:log buffer里的redo log会被刷到磁盘里(changes are fixed in log file via log buffer)

operating system cache:内存和磁盘之间,不属于innodb的能力,而是操作系统为了提升性能,在磁盘前面假的一层高速缓存(page cache)

而Innodb的磁盘架构除了表结构定义和索引(表数据都以索引的形式存储起来了)还包含了一些别的角色,redo log,undo log,change buffer,doublewrite buffer等。

doublewrite buffer:如果说change buffer是为了提升性能,那么doublewrite buffer就是为了保证数据页的可靠性。比如内存刷到磁盘的时候,一个页刷了一半,突然系统或者mysql进程崩溃了,这个时候,内存的页数据被清除了,而磁盘的页数据刷到一半,此时redo log已经无力回天,redo log只能是磁盘中的页数据是正常的情况下,才能把磁盘的页数据load到内存,然后做成redo log,如果磁盘的页数据损坏是没有办法应用redo log的。所以mysql刷数据到磁盘之前,要先把数据写到另外一个地方,也就是doublewrite buffer,写完后再开始刷盘,如果磁盘页有问题可以用doublewrite buffer来恢复磁盘页数据。

redo log是为了持久化而生的,写完内存,如果数据库挂了,那我们可以通过redo log来恢复内存还没来得及刷到磁盘的数据。

redo log是事务开始的时候,就开始记录每次的变更信息,binlog是在事务提交的时候才会记录。

于是新有的问题又出现了:我写其中的某一个log,失败了,那会怎么办?现在我们的前提是先写redo log,再写binlog,我们来看看:

  • 如果写redo log失败了,那我们就认为这次事务有问题,回滚,不再写binlog
  • 如果写redo log成功了,写binlog,写binlog写一半了,但失败了怎么办?我们还是会对这次的事务回滚,将无效的binlog给删除(因为binlog会影响从库的数据,所以需要做删除操作)
  • 如果写redo logbinlog都成功了,那这次算是事务才会真正成功。

简单来说:MySQL需要保证redo logbinlog数据是一致的,如果不一致,那就乱套了

Mysql通过两阶段提交来保证redo log和binlog的数据是一致的。

update的流程(每个事务的binlog末尾都会记录一个XID event,标志着事务是否提交成功(binlog没记录成功,有可能mysql宕机等因素),也就是说恢复过程中,binlog最后一个XID event之后的内容都应该被purge)

  • mysql客户端告诉mysql server层我要修改第2条的name变成XXX
  • mysql server层告诉innodb存储引擎,把第2条的name变成XXX
  • innodb将修改内容记录到redo log buffer
  • innodb在redo log里面记录第几页的什么地方做了什么修改,事务进行prepare状态
  • innodb告诉mysql server层修改好了,可以提交事务了
  • mysql server层提交事务,记录binlog
  • innodb里面将这个事务进入commit状态

undo log

两个作用:回滚和多版本控制(MVCC)

数据修改的时候不止记录了redo log还记录了undo log,如果因为某些原因导致事务失败或回滚了,可以用undo log进行回滚。undo log记录的也是逻辑日志,我们insert一条记录,那undo log就会记录一个delete日志,因为undo log存储的是修改之前的数据,相当于一个前版本,MVCC实现的是读写不阻塞,读的时候只要返回前一个版本的数据就行。

几个问题

1.mysql主键不连续的原因?

自增键保存在内存里,每次重启后,第一次打开表的时候,都会去找自增值的最大值max(id) ,将max(id) +1座位这个表当前的自增值

  • 唯一键冲突导致
  • 事务回滚
  • 批量插入 ,第一次申请自增id,会分配一个,1个用完了,还是这个语句,第二次申请自增id,会分配2个,第三次分配4个,如果只用到id3,id4就被浪费了,之后再有插入语句,从id5开始

2.int(5)和int(11)区别,int和smallint区别

  • int(11)中,11代表的并不是长度,而是字符的显示宽度,在字段类型为int时,无论你显示宽度设置为多少,int类型能存储的最大值和最小值永远都是固定的(字段b,长度不足11,左边自动补零

    字段d,长度超过了5,仍然可存储,这是显示宽度就不起作用了。)

  • 字段b,类型int(11),值为1,则存储为: 00000000001

    字段d,类型int(5),值为1234567890,仍然可以存储为:1234567890 这10个数字

  • tinyint带符号-128到127,无符号范围0到255,默认4;tintint(1)值为1是真,0是假

  • smallint带符号-32768到32767,无符号范围0到65535,默认65535【2的16次幂】,默认值为6

  • int带符号的范围是-2147483648到2147483647。无符号的范围是0到4294967295【2的32次幂,4位,每位8个字节】,默认11

  • bigint带符号的范围是-9223372036854775808到9223372036854775807。无符号的范围是0到18446744073709551615

3.索引下推

索引下推在非主键索引上的优化,可以有效减少回表的次数,大大提升了查询的效率。

  • InnoDB并没有忽略age这个字段,而是在索引内部就判断了age是否等于20,对于不等于20的记录直接跳过,因此在(name,age)这棵索引树中只匹配到了一个记录,此时拿着这个id去主键索引树中回表查询全部数据,这个过程只需要回表一次

4.前缀索引

当一个文本很长时,还想检索

  • 可以设置前缀索引
  • 对某个字段进行加密,存成另外一个字段,根据新字段去找


blog comments powered by Disqus