MySQL 普通/唯一索引

身份证号字段较大,一般创建唯一索引或 普通索引

唯一/普通索引区别 :

  • 查询的性能相差较小
  • 更新语句性能 : 普通索引高效

查询性能

在索引树上查找的过程 :

  • 普通索引 : 找到满足条件的第一个记录后,还要查找下一个记录,直到不满足该条件的记录
  • 唯一索引 : 找到第一个满足条件的记录后,就停止检索

性能差距较小的原因 :

  • InnoDB 的数据是按数据页 (默认 : 16KB ) 为单位来读写

更新性能

向表中插入记录的情况 :

  • 记录在内存中
  • 记录没在内存中

记录在内存中的流程 :

  • 普通/唯一索引相差较小
  • 唯一索引 : 找到插入位置,判断其没有冲突,插入该值,语句执行结束
  • 普通索引 : 找到插入位置,插入该值,语句执行结束

记录没在内存中的流程 :

  • 数据从磁盘读入内存 , 涉及随机 IO 访问 , 成本较高
  • 唯一索引 : 将数据从磁盘中读入内存,判断其没有冲突,插入该值,语句执行结束
  • 普通索引 : 将更新记录在 change buffer,语句执行就结束

change buffer

change buffer 只适合普通索引,并不适用唯一索引

普通索引加速场景 :

  • 写多读少 : change buffer 缓存大量数据 , 并统一 merge 后对数据更新 。业务场景 : 账单类、日志类
  • 读多写少 : 更新后立马查询 , 记录在 change buffer 后 , 就会立马 merge , 随机访问 IO 未减少

change buffer 用的是 buffer pool 里的内存

change buffer 大小 :

# change buffer 大小 : 最多占 buffer pool 的 50%
innodb_change_buffer_max_size = 50

change buffer/redo log

  • redo log 节省 : 随机写磁盘的 IO 消耗(转成顺序写)
  • change buffer 节省 : 随机读磁盘的 IO 消耗

change buffer 更新过程 :

  1. Page 1 在内存中,直接更新内存
  2. Page 2 没有在内存中,就在内存的 change buffer ,记录下 “往 Page 2 插入一行” 信息
  3. 两个动作记入 redo log 中 (3 ,4)

image.png

change buffer 读过程 :

  1. 读 Page 1 时,直接从内存返回
  2. 读 Page 2 时,要把 Page 2 从磁盘读入内存中,并把 change buffer 中的操作日志,生成正确版本 , 并返回结果

image.png

索引选择实践

当考虑更新性能问题时 , 考虑用普通索引 , 并加大 change buffer

  • 场景 : 历史数据保存在归档库