Java学习笔记 Mysql

mysql

约束与外键

约束是对数据库表中数据的一些限制条件,目的是为了保证表中数据的完整性和有效性。

  1. 主键约束:mysql的主键约束可以是一列或者多个列的组合,用于唯一标识表中的每一行,主键约束列的数值不允许重复或为空值。给字段添加primary key属性可以将该字段设置为
  2. 自增长约束:mysql中可以将主键定义为自增长,这样在插入新数据时就不需要再输入主键,数据库会用自增长的方式为每一条数据自动赋值。通过给主键添加auto_increment属性可以实现。
  3. 非空约束:定义某一字段不能为空,关键字为not null。
  4. 唯一约束:设置某一字段不能有重复的值,关键字为unique。
  5. 默认约束:为某一字段添加默认值,关键字为default。
  6. 零填充约束:输入数据时如果某一字段的值的长度小于设定的长度,会在值前面补上相应数量的0,关键字为zerofill。
    外键是一个表中的一列,它同时又包含在另一个表的主键中,将两个表进行关联。外键可以保证数据的一致性和完整性,减少数据冗余。
  • 外键约束:一个表中国的外键如果不为空,则它必须与另一个表中主键的某个值相等。

MySql(B站河北王校长视频学习笔记)

B+树

B+树的存储特点(以聚簇索引为例)

根结点16kb内存页,可以存储161024/(8+6)=1170个(8字节bigint类型的primary key + 6字节指针),则B+树的第二层有1170个节点,每个节点也可以存储1170个(primary key + 指针),则第三层有11701170个节点。如果一条数据的内存是1kb,那么该B+树可以存储1170117016条数据。

mysql每访问一个结点就需要进行加载一次内存页,加载完成之后通过二分查找定位id范围,然后指向下一层。

为什么不用B树?
  • B树:每个节点都会存储mysql数据

假设一条mysql 数据的内存是1kb,B树的根结点只能存储16条数据+指针,第二层只能存储16*16条数据。假设mysql需要存储1000万条数据,使用B+树只需要3层,即进行三次IO就能找到,而使用B树需要很多层,也就需要进行很多次IO。

为什么不用HashMap?
  1. HashMap是依据hashcode进行存储,不支持模糊查询
  2. HashMap的hashcode是随机的,无法进行范围查询
  3. 会发生Hash冲突

索引

聚簇索引(聚集索引)

以每张表的primary key为索引构造的索引树

  • 每张表只有一个聚集索引B+树
  • 叶子节点存储select* 整行数据
  • 非叶子节点存储primary key主键+指向下一节点的指针
非聚簇索引(辅助索引)
  • 每张表可以有多个辅助索引
  • 叶子节点存储所有索引
  • 非叶子节点存储索引+6字节指针

当使用如下语句进行辅助索引时,在辅助索引中定位到数据时需要使用叶子节点中的主键id回到聚簇索引进行回表查询。

select* from [table] where [辅助索引]   
联合索引

联合索引也是通过B+树创建。

如何给表定义索引?
  • 随机度越高,定义为索引时索引的效率越高。例如将性别作为索引就不助于查询(创建索引也会给表带来一定负担),而日期随机性高就很适合作为索引进行定义。
如何判断字段的值是否离散?
show index;

使用该命令查看cardinality的值,如果cardinality的值越接近1说明该字段离散性越高。cardinality的值会随着数据的更新和改变发生变化。

覆盖索引(不属于索引,只是一种效果)
  select name from [table] where name = ‘zhangsan’

该查找语句由于name辅助索引的叶子节点包含name字段的索引值,就不需要回调聚簇索引,达到覆盖索引的效果。假设该表的索引树只有三层,那么只需要发生3次IO就能得到数据。

  select * from [table] where name = ‘zhangsan’

该查找语句由于需要查找所有字段的值,所以会先在name辅助索引的叶子节点拿到 name=‘zhangsan’ 和id的值,然后回传到聚簇索引通过id找到完整数据并返回。假设该表的索引树只有三层,那么就需要发生6次IO。

什么情况下索引会失效?

王校长记忆法:LOL; ±*/; not null; no method; no convert; 我就是我,不一样的版本不一样的我;

  1. LIKE:当like语句中的参数以%开头时索引会失效
  2. OR:当or前后两个字段中有至少一个不为索引的时索引会失效
  3. 联合查询:创建联合索引(a, b),如果where条件没有从联合索引的首元素索引开始索引,那么索引会失效(最左匹配原则)
select [] from [table] where a > 3 and b > 5
-- 此时会使用索引 
select [] from [table] where b > 5
-- 此时不会使用索引 
  1. ±*/ :当索引列进行运算时索引失效
  2. not:当索引列使用 != ,<> ,is not 等时索引会失效
  3. null:当索引列使用is null,is not null时索引可能会失效(是否失效与版本有关,mysql允许索引为null,但在创建索引树时只对索引不为null的数据进行创建;在创建字段时需要将不可能为空的字段设置为非空字段,对可能为空的字段设置default默认值,以确保在对字段加索引时能够将所有数据构建到B+树的节点)
  4. no method:当索引列使用到mysql内置函数时索引会失效
  5. no convert:假设mysql中字段类型为varchar,但进行查询时使用了id=12345,mysql会使用内置函数convert把数字类型的12345转换成varchar类型后再进行索引,此时索引会失效。
  6. 版本:
select * from [table] where a > 3 -- a是辅助索引

mysql5.6(不包括)之前由于存在离散读的问题,该语句会进行全表扫描,不会使用辅助索引(3次IO扫全表)。还可能根据阈值对查询数据的范围进行判断是否使用辅助索引。

mysql5.6(包括)之后,该语句会通过辅助索引获取主键id,将数据缓存并根据进行排序(在innodb引擎层完成),在使用聚簇索引获取数据时会按照id的顺序进行查询,如果两条数据间的间隔不大,在查询到第一条数据时则会继续向后读取拿到下一条数据,如果间隔较大则重新进行查询。

离散读

mysql5.6之前,在辅助索引返回的结果回到聚簇索引进行查询整行数据时,需要对每一条数据都进行查询,每条数据都进行三次IO,开销较大。

MVCC(一致性非锁定读、多版本并发控制)

MVCC是mysql基于自身的回滚机制(undolog)为并发场景下的读操作提供的多版本控制,为达到读操作不需要被锁定的目的来加快mysql的读取。

不同隔离级别下MVCC的表现

mysql的四种隔离级别:read uncommitted、read committed、repeatable read(默认隔离级别)、serialize

  • repeatable read(默认隔离级别):视图在每次select时创建,事务期间的select都使用这个视图。(此隔离级别下需要通过间隙锁解决幻读问题)
  • read committed:视图在每次select时生成,读取的数据是最后一次提交的数据版本;读取的数据受其他事务的影响,违背了事务的隔离性;会造成幻读(相同语句读取数据返回的结果数量不同)和不可重复读(相同语句读取数据返回的结果数据不同)
  • read uncommitted:读取的是最后一次修改的数据版本;会读到没有进行持久化的脏数据,发生脏读
  • serialize:用加锁的方式让所有操作串行进行,无并发
Mysql锁的三种算法
InnoDB引擎下的行级锁
  • 共享锁(S Lock):允许事务读一行数据
  • 排他锁(X Lock):允许事务删除或更新一行数据
    S与S兼容,其他情况均不兼容
InnoDB引擎的3种行锁的算法
  • Record Lock:单个行记录上的锁,锁定索引记录(如果没有设置索引则会使用隐式主键进行锁定)
  • Gap Lock:间隙锁,锁定一个范围,但不包括记录本身
  • Next-Key Lock(默认隔离级别下的锁定算法):行锁+间隙锁,锁定一个范围,并锁定记录本身

假如一个索引有10,11,13,20这四个值,那么索引可能被Next-Key Lock的区间为:(-§ , 10] , (10 , 11] , (11 , 13] , (13 , 20] , (20 , +§)

当查询的索引含有唯一属性时,会对Next-Key Lock进行优化,降为Record Lock,仅锁住索引本身,而不是范围。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值