小林coding-mysql学习笔记

date8.5

1,MySQL 的 NULL 值是怎么存放的?

MySQL 的 Compact 行格式中会用「NULL值列表」来标记值为 NULL 的列,NULL 值并不会存储在行格式中的真实数据部分。

NULL值列表会占用 1 字节空间,当表中所有字段都定义成 NOT NULL,行格式中就不会有 NULL值列表,这样可节省 1 字节的空间。

2,MySQL 怎么知道 varchar(n) 实际占用数据的大小?

MySQL 的 Compact 行格式中会用「变长字段长度列表」存储变长字段实际占用的数据大小。

3,varchar(n) 中 n 最大取值为多少?

一行记录最大能存储 65535 字节的数据,但是这个是包含「变长字段字节数列表所占用的字节数」和「NULL值列表所占用的字节数」。所以, 我们在算 varchar(n) 中 n 最大值时,需要减去这两个列表所占用的字节数。

如果一张表只有一个 varchar(n) 字段,且允许为 NULL,字符集为 ascii。varchar(n) 中 n 最大取值为 65532。

计算公式:65535 - 变长字段字节数列表所占用的字节数 - NULL值列表所占用的字节数 = 65535 - 2 - 1 = 65532。

如果有多个字段的话,要保证所有字段的长度 + 变长字段字节数列表所占用的字节数 + NULL值列表所占用的字节数 <= 65535。

4,行溢出后,MySQL 是怎么处理的?

如果一个数据页存不了一条记录,InnoDB 存储引擎会自动将溢出的数据存放到「溢出页」中。

Compact 行格式针对行溢出的处理是这样的:当发生行溢出时,在记录的真实数据处只会保存该列的一部分数据,而把剩余的数据放在「溢出页」中,然后真实数据处用 20 字节存储指向溢出页的地址,从而可以找到剩余数据所在的页。

Compressed 和 Dynamic 这两种格式采用完全的行溢出方式,记录的真实数据处不会存储该列的一部分数据,只存储 20 个字节的指针来指向溢出页。而实际的数据都存储在溢出页中。

5,索引的分类

按「数据结构」分类:B+tree索引、Hash索引、Full-text索引。 按「物理存储」分类:聚簇索引(主键索引)、二级索引(辅助索引)。 按「字段特性」分类:主键索引、唯一索引、普通索引、前缀索引。 按「字段个数」分类:单列索引、联合索引。

6,索引优化的思路

前缀索引优化; 覆盖索引优化; 主键索引最好是自增的;(主键最好小-》b+树的节点变小) (这样新插入的数据直接进行追加写入,不需要进行移动树的节点,降低了操作的时间) (如果不这么做,会导致页分裂(innodb的数据结构,行-》页-》区-》段-》表空间)) 防止索引失效;

7,innodb中的行信息

其中编码格式也会影响存储大小(asill和utf-8的字节分别为1字节和3字节) 变长字段长度列表、NULL 值列表、记录头信息 变长字段长度列表 null值列表(最少一个字节),反向存储01用于辨别该键值对是否为null

8,为什么索引中尽量不要null值

第一原因:索引列存在 NULL 就会导致优化器在做索引选择的时候更加复杂,更加难以优化,因为可为 NULL 的列会使索引、索引统计和值比较都更复杂,比如进行索引统计时,count 会省略值为NULL 的行。

第二个原因:NULL 值是一个没意义的值,但是它会占用物理空间. InnoDB 存储记录的时候,如果表中存在允许为 NULL 的字段,那么行格式中至少会用 1 字节空间存储 NULL 值列表(你要有8个NULL值那就变成2字节的null列表)

9,快照读和普通读

MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象(并不是完全解决了,详见这篇文章),

解决的方案有两种: 针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。

针对当前读(select ... for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP