MySQL主键设计问题

159 阅读2分钟

这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

  • mysql每个表必须有主键

    • 如果没有显式指定主键,mysql会按照如下方式选择或者创建主键

      • 如果表中有非空的唯一索引,采用该列为主键

      • 如果多个非空唯一索引,采用第一个索引作为主键

      • 如果什么也没有,InnoDB会⾃动创建⼀个6字节⼤⼩的指针作为索引主键

  • 主键不宜设置太长

    • 主键如果设置过长,首先就会占用过多空间(不过这点影响其实可以忽略不计)。

    • **(主要原因)**InnoDB是非聚簇索引,的叶子存储的是主键的值而非指针!如果主键太长了,那么叶子节点能存储的数据就少了,这样在有限的索引缓存中,就需要多次读取磁盘,性能会下降。叶子大了,一次能拿的就少了,IO就高了。

    • 综上来说,尽量让主键不要太长的核心还是为了减少IO。

  • 为什么建议用自增ID,而不是UUID等?

    • 因为主键索引是聚集索引,mysql的行数据会存在主键索引的叶子节点。当insert新数据的时候,mysql需要按照主键顺序插入数据行,如果是自增的,那么数据会被顺序的写入磁盘页中,

    • 如果不是自增的,那么插入也是随机的,这就需要移动数据,会造成频繁的刷新缓冲,增加磁盘IO,并且对于索引频繁的重建。而顺序插入,不影响左子树,只是append操作。

    • 综上2个原因:叶子节点需要移动数据,索引需要重建。影响性能!

    • good: 顺序IO。bad: 随机IO,需要移动3,4img

    • 其他的如:UUID等字符串占用更多存储空间,整型进行比较速度快。

  • mysql Id自增的原理

    • mysql内存中维护一个自增计数器 auto-increment来累加自增的id