设计MySQL数据库表的时候,一定会考虑主键的设计。mysql官方推荐不要使用uuid或者不连续不重复的雪花id,推荐连续自增的主键id,官方的推荐是auto_increment。为什么不建议采用uuid,使用uuid究竟有什么坏处?

如果设计表不设置主键,MySQL官方有以下说明:

If you do not define a PRIMARY KEY for your table, MySQL picks the first UNIQUE index that has only NOT NULL columns as the primary key and InnoDB uses it as the clustered index. If there is no such index in the table, InnoDB internally generates a clustered index where the rows are ordered by the row ID that InnoDB assigns to the rows in such a table. The row ID is a 6-byte field that increases monotonically as new rows are inserted. Thus, the rows ordered by the row ID are physically in insertion order.

翻译:如果没有主动设置主键,就会选一个第一个不包含NULL的唯一索引列作为主键列,并把它用作一个聚集索引。如果没有这样的索引就会使用行号生成一个聚集索引,把它当做主键,这个行号6bytes,自增。可以用select _rowid from table来查询。

1. 什么是主键?主键有什么用

mysql 数据库表存放关系型结构化数据,一定会提供对数据的CRUD操作。在查询操作时,如果没有索引,MySQL必须从第一行开始,然后读取整个表以查找相关行。表越大,成本越高。通过建立索引,MySQL可以根据索引文件快速确定要在数据文件中间寻找的位置,而无需查看所有数据。

MySQL的索引主要分为主键索引(PRIMARY KEY),唯一索引(UNIQUE) ,普通索引(INDEX)和全文索引(FULLTEXT) 。主键索引是一种特殊的唯一索引,不允许有空值。

MySQL中索引是如何发挥功效的呢?先看一下MySQL的执行过程:

所有与数据的交互是会通过引擎服务的,MySQL中常见的引擎包括MyIsam和InnoDb。二者的差别这里不做叙述,可参见:CSDNhttps://mp.csdn.net/mp_blog/creation/editor/96205289

InnoDB的存储文件有两个,后缀名分别是 .frm和 .idb;其中 .frm是表的定义文件, .idb是表的数据文件。InnoDB引擎采用B+Tree结构来作为索引结构,InnoDB主键的叶子节点是该行的数据,而其他索引则指向主键。

2. 为什么不推荐使用UUID

页是 InnoDB 管理的最小单位,常见的有 FSP_HDRINODE, INDEX 等类型。页结构分为文件头(前38字节),页数据和文件尾(后8字节)。每个数据页大小为16kb,结构如下:

系统从磁盘中读取数据到内存时是以磁盘块(block)为基本单位,位于同一个磁盘块中的数据会被一次性读取出来。block大小空间往往没有16kb大,因此innodb每次io操作时都会将若干个地址连续的磁盘块的数据读入内存,从而实现整页读入内存。

MySQL写入数据时,会把数据存放到索引页中。使用UUID作为主键,新行的主键值不一定比之前的主键值大,所以innoDb无法做到总是把新行插入到索引的最后,而需要为新行寻找合适的位置来分配新的空间,这个过程会导致:

  • 写入的目标页可能从缓存上移除了,或者还没有加载到缓存上,innodb写入之前需要先从磁盘找到目标页,会产生大量的随机IO;
  • 因为写入是乱序的,innoDb 要做频繁的分页操作,以便为行产生新的空间,页分裂导致移动大量的数据,一次插入最少需要修改三个页以上;
  • 频繁的页分裂,页会变得稀疏并被不规则的填充,最终会导致数据会有碎片;
  • 随机值(uuid和雪花id)载入到聚簇索引,有时候会需要做一次OPTIMEIZE TABLE来重建表并优化页的填充,这将又需要一定的时间消耗。

使用自增主键则可以避免上述问题:

  • 自增主键值是顺序的,所以Innodb把每一条记录都存储在一条记录的后面。当达到页面的最大填充因子时候(innodb默认的最大填充因子是页大小的15/16,会留出1/16的空间留作以后的     修改),下一条记录就会写入新的页中;
  • 数据按照顺序方式加载,主键页就会近乎于顺序的记录填满,提升了页面的最大填充率,不会有页的浪费;
  • 新插入的行一定会在原有的最大数据行下一行,mysql定位和寻址很快,不会为计算新行的位置而做出额外的消耗;
  • 减少了页分裂和碎片的产生

结论:使用innodb应该尽可能的按主键的自增顺序插入,并且尽可能使用单调的增加的聚簇键的值来插入新行

3. 使用自增主键的问题

  • 安全问题:如果采用自增主键,可能存在根据ID值爬取数据库记录,有安全风险;
  • 系统重构:系统重构或者与其他系统集成时,可能存在新老主键冲突;
  • 高并发负载,innodb在按主键进行插入的时候会造成明显的锁争用,主键的上界会成为争抢的热点,因为所有的插入都发生在这里,并发插入会导致间隙锁竞争;
  • Auto_Increment锁机制会造成自增锁的抢夺,有一定的性能损失;
  • 自增主键有限,要考虑主键长度问题。

Auto_increment的锁争抢问题,可以通过调优innodb_autoinc_lock_mode的配置,总共有三个有效值可供设定,即0、1、2,具体说明如下:

0:是MySQL 5.1.22版本之前自增长的实现方式,即通过表锁的AUTO-INC Locking方式,所有的insert语句在开始时都会获得一个表锁AUTO-INC Locking。该锁会一直持有到insert语句执行结束才会被释放。对于一条insert插入多个行记录的语句,保证了同一条语句插入的行记录的自增ID是连续的。

1:这是该参数的默认值,对于”simple inserts”,该值会用互斥量(mutex)去对内存中的计数器进行累加的操作。insert语句在开始时会获得一个表锁AUTO-INC Locking,但对于bulk insert,自增锁会被一直持有直到语句执行结束才会被释放。这种模式仍然保证了同一条语句插入的行记录的自增ID是连续的。

2:对于所有的插入操作”INSERT-LIKE”自增长值的产生都是通过互斥量,而不是AUTO-INC Locking的方式,不管什么情况都使用轻量级互斥的锁。因为并发插入的存在,在每次插入时,自增长的值可能不是连续的。最重要的是,基于Statement的主从复制会出现问题,任何时候都应该使用Row方式,这样才能保证最大的并发性能及主从数据的一致。

MySql为什么不推荐使用UUID做主键相关推荐

  1. mysql uuid 做主键_MySQL UUID做主键

    UUID做主键,好还是不好?这是个问题. 我唯一还算熟悉的数据库就算是MySQL了,大概使用MySQL的人,百分之九九以上的人会使用Autoincrement ID做主键,这是可以理解的,因为MySQ ...

  2. 为什么不要用uuid做主键

    之前文章中介绍Snowflake的时候其实已经说过了,自增id做主键对于InnoDB更友好,如果用uuid做主键数据插入时会伴随大量的数据迁移,导致插入性能降低,今天从InnoDB数据结构聊聊数据是如 ...

  3. Java代码TkMyBatis通用Mapper中新增数据时同时获取自增主键ID,与适用uuid 做主键时获取 id

    一 . MyBatis mapper.xml文件中在xml 1.   加入 这句 :useGeneratedKeys="true" keyProperty="ID&quo ...

  4. 为什么是UUID做主键

    为什么是UUID做主键 什么是UUID UUID是通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准.其目的,是让分布式系统中的所有元素都能有唯一 ...

  5. mysql int做主键_mysql5.5 uuid做主键与int做主键的性能实测

    偶然的机会,得知mysql主键的类型采用 varchar 存UUID 的查询性能没有int型做主键好.网上查询大量资料,都是停留在理论上的,因此,自己写了代码进行实测,以下结果仅供参考,不具备权威性. ...

  6. centos修改磁盘uuid_为什么MySQL用uuid做主键会被骂?

    " 在 MySQL 中设计表的时候,MySQL 官方推荐不要使用 uuid 或者不连续不重复的雪花 id(long 形且唯一,单机递增),而是推荐连续自增的主键 id,官方的推荐是 auto ...

  7. MySQL之——mysql5.5 uuid做主键与int做主键的性能实测

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/51140577 偶然的机会,得知mysql主键的类型采用 varchar 存UUID ...

  8. mysql为何不建议使用外键_为什么很多mysql课程不推荐用物理外键?

    刚好今晚有师弟问我这个问题,就来搜搜.以前我对这个也是蛮困惑的.这一年来对这个问题感受比较深. 用外键的好处我就不多说了,既然是关系型数据库,外键的约束为我们保证了数据主从关系和产生的先后关系,级联操 ...

  9. 数据库-玩转数据-Pgsql 使用UUID做主键

    一.使用uuid-ossp 1.安装 uuid-ossp 文件: 在postgresql数据库中,是不能直接使用UUID函数的,需要手动安装 uuid 的相关文件,才能应用UUID相关的函数. 2.调 ...

最新文章

  1. 轻量应用服务器MySQL远程连接踩坑
  2. 25个视频神同步,还能给视频声音移花接木,谷歌开源最新自监督算法
  3. 输出某个目录下的所有文件和文件夹,包括子文件夹中的内容
  4. 借助格式化输出过canary保护
  5. 腾讯Tiny OS 组合 NB-IoT,值得程序员一试吗?
  6. Unity3d 通过协程来实现文件的全部加载后执行
  7. matlab中input输入多个数_python怎么一次输入两个数
  8. MYSQL的空间查询
  9. 利用后中遍历结果,重构二叉树
  10. jsp实现简易购物车
  11. 扩展Win7虚拟机硬盘
  12. 迁移操作系统:如何把系统迁移到固态硬盘SSD?
  13. HDMI EDID timing详细解析
  14. 第四届“橙瓜网络文学奖”暨见证·网络文学20年评选各类型十佳大神入围名单
  15. AMBA总线---APB总线协议
  16. MySQL查询和删除重复记录
  17. 编写判断一个正整数是否为素数的函数
  18. 移动端加载MVT矢量瓦片
  19. 华为手机承载系统在哪里_华为鸿蒙OS系统取得重大突破!华为手机新系统真的来了:兼容安卓10...
  20. 中国移动的5G套餐定价亲民,决心在5G时代争先

热门文章

  1. 最大相关性最小冗余性(mrmr)
  2. uniapp 动态 tabbar
  3. 来客小讲堂之视频号直播推广技巧
  4. 宝开框架研究——资源管理
  5. python可以用tab缩进吗_python缩进可以用tab吗
  6. 问题解决 Cannot calibrate from current position
  7. ESP32+PIO+LGVL+gui_guider之【BUTTON实体按键】
  8. 华为外部Portal认证 Radius认证计费 实现基于Mac快速认证的Mac无感知认证和结合CAS单点登录统一认证平台和AD域LDAP对接配置
  9. 使用从create-react-app创建项目后,运行npm run eject报错解决方法
  10. 天池--优惠卷预测比赛讲解-特征提取