《mysql45讲》小记

2021/03/05 Mysql

《mysql45讲》小记

目录

«mysql45讲»

第三讲-事物隔离

1.事物

提到事务,你肯定会想到 ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)

2.隔离

SQL 标准的事务隔离级别包括:读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(serializable )。

下面我逐一为你解释:
    a.读未提交是指,一个事务还没提交时,它做的变更就能被别的事务看到。
    b.读提交是指,一个事务提交之后,它做的变更才会被其他事务看到。
    c.可重复读是指,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。
      当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。
    d.串行化,顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,
      后访问的事务必须等前一个事务执行完成,才能继续执行。

第四讲-索引

1.什么是索引

索引的出现其实就是为了提高数据查询的效率,就像书的目录一样。

2.索引常见模型

哈希表:
    1.适用于等值查询场景(直接按key查找)。
    2.不适用于按区间查找,无序的,区间查询需要全部遍历一遍。
有序数组:
    1.有序数组在等值查询和范围查询场景中的性能就都非常优秀。
      单个和区间查找都可以用二分查找加速查询,时间复杂度O(logN)。
    2.缺点更新数据太麻烦,中间插入记录需要挪动后面所有数据,只适用于
      静态存储引擎,比如保存的数据不会再修改。

二叉搜索树:
    1.二叉搜索树的特点是:每个节点的左儿子小于父节点,父节点又小于右儿子。这样如果你要查 ID_card_n2 的话,
      按照图中的搜索顺序就是按照 UserA -> UserC -> UserF -> User2 这个路径得到。这个时间复杂度是 O(log(N))。
    2.当然为了维持 O(log(N)) 的查询复杂度,你就需要保持这棵树是平衡二叉树。
      为了做这个保证,更新的时间复杂度也是 O(log(N))
    3.二叉树是搜索效率最高的,但是实际上大多数的数据库存储却并不使用二叉树。其原因是,索引不止存在内存中,还要写到磁盘上。
    4.为了让一个查询尽量少地读磁盘,就必须让查询过程访问尽量少的数据块。那么,我们就不应该使用二叉树,而是要使用“N 叉”树。
      这里,“N 叉”树中的“N”取决于数据块的大小。
    5.以 InnoDB 的一个整数字段索引为例,这个 N 差不多是 1200。这棵树高是 4 的时候,就可以存 1200 的 3 次方个值,这已经 17 亿了。
     考虑到树根的数据块总是在内存中的,一个 10 亿行的  表上一个整数字段的索引,查找一个值最多只需要访问 3 次磁盘。
     其实,树的第二层也有很大概率在内存中,那么访问磁盘的平均次数就更少了。 

3.InnoDB 的索引模型

1.每一个索引在 InnoDB 里面对应一棵 B+ 树.

2.主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index):
  如上图左,例如:主键ID为300,叶子节点为100~600是说明主键ID这行,字段的值为100~600。
  
  非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index):
  如上图右,例如:字段值为3,也子节点1,2,3,5,6是主键值。

3.在查询整行数据值时,基于主键索引查找优于基于普通索引查找(主键是一种唯一性索引(默认),必须指定为“PRIMARY KEY”。):
  a.如果语句是 select * from T where ID=500,即主键查询方式,则只需要搜索 ID 这棵 B+ 树;
  b.如果语句是 select * from T where k=5,即普通索引查询方式,则需要先搜索 k 索引树,
    得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程称为回表。 
  
  基于非主键索引的查询需要多扫描一棵索引树
索引维护:
    1.以上面这个图为例,如果插入新的行 ID 值为 700,则只需要在 R5 的记录后面插入一个新记录。
      如果新插入的 ID 值为 400,就相对麻烦了,需要逻辑上挪动后面的数据,空出位置。
    2.而更糟的情况是,如果 R5 所在的数据页已经满了,根据 B+ 树的算法,这时候需要申请一个新的数据页,
      然后挪动部分数据过去。这个过程称为页分裂。在这种情况下,性能自然会受影响。
    3.除了性能外,页分裂操作还影响数据页的利用率。原本放在一个页的数据,现在分到两个页中,整体空间利用率降低大约 50%。
    4.当然有分裂就有合并。当相邻两个页由于删除了数据,利用率很低之后,会将数据页做合并。
      合并的过程,可以认为是分裂过程的逆过程。

自增主键:
  1.自增主键是指自增列上定义的主键,在建表语句中一般是这么定义的: NOT NULL PRIMARY KEY AUTO_INCREMENT。
  插入新记录的时候可以不指定 ID 的值,系统会获取当前 ID 最大值加 1 作为下一条记录的 ID 值。
  也就是说,自增主键的插入数据模式,正符合了我们前面提到的递增插入的场景。每次插入一条新记录,都是追加操作,都不涉及到挪动其他记录,也不会触发叶子节点的分裂。
  而有业务逻辑的字段做主键,则往往不容易保证有序插入,这样写数据成本相对较高。
  2.除了考虑性能外,我们还可以从存储空间的角度来看。假设你的表中确实有一个唯一字段,比如字符串类型的身份证号,那应该用身份证号做主键,还是用自增字段做主键呢?
   由于每个非主键索引的叶子节点上都是主键的值。如果用身份证号做主键,那么每个二级索引的叶子节点占用约 20 个字节,而如果用整型做主键,则只要 4 个字节,如果是长整型(bigint)则是 8 个字节。显然,主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。

4.覆盖索引


Search

    Table of Contents