首页 > 数据库 >为什么不推荐用 UUID 作为 Mysql 的主键

为什么不推荐用 UUID 作为 Mysql 的主键

时间:2024-01-27 20:33:07浏览次数:30  
标签:自增 分库 UUID 主键 Mysql 数据 id

学习改变命运,技术铸就辉煌。

大家好,我是銘,全栈开发程序员。

UUID 是什么

我们先来了解一下 UUID 是什么?UUID 是指Universally Unique Identifier,翻译为中文是通用唯一识别码,UUID 的目的是让分布式系统中的所有元素都能有唯一的识别信息。如此一来,每个人都可以创建不与其它人冲突的 UUID,就不需考虑数据库创建时的名称重复问题。

UUID 的十六个八位字节被表示为 32个十六进制数字,以连字号分隔的五组来显示,形式为 8-4-4-4-12,总共有 36个字符(即三十二个英数字母和四个连字号)。例如:

123e4567-e89b-12d3-a456-426655440000
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

能否用 UUID 做主键

先说答案 , 能,但是性能会比使用自增主键差一些,那原因是什么,我们具体分析:

我们平时建表的时候,一般都像下面这样,不会去使用 UUID,使用AUTO INCREMENT直接把主键 id 设置成自增,每次 +1

CREATE TABLE `user`(
`id` int NOT NULL AUTO INCREMENT COMMENT '主键',
`name` char(10) NOT NULL DEFAULT '' COMMENT '名字',
 PRIMARY KEY (`id`)
 )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

那为什么把主键设置成自增呢, 我们在数据库保存数据的时候,就类似与下面的表格一样,这每一行数据,都是**保存在一个 16K 大小的页里 **。

id name age
1 张三 11
2 李四 22
3 王五 33

每次都去遍历所有的行性能会不好,于是为了加速搜索,我们可以根据主键 id,从小到大排列这些行数据,将这些数据页用双向链表的形式组织起来,再将这些页里的部分信息提取出来放到一个新的 16kb 的数据页里,再加入层级的概念。于是,一个个数据页就被组织起来了,成为了一棵 B+ 树索引。

当我们在建表 sql 里面声明 AUTO INCREMENT 的时候,myqsl 的 innodb 引擎,就会为主键 id 生成一个主键索引,里面就是通过 B+ 树的形式来维护这套索引。

那么现在,我们需要关注两个点,

  1. 数据页大小是固定的 16k
  2. 数据页内,以及数据页之间,数据主键 id 是从小到大排序的

所以,由于数据页大小固定了 16k ,当我们需要插入一条数据的时候,数据页就会慢慢的被放满,当超过 16k 的时候,这个数据页就可能会进行分裂。

针对 B+ 树的叶子节点,如果主键是自增的,那么它产生的 id 每次都比前次要大,所以每次都会将数据家在 B+ 树的尾部,B+ 树的叶子节点本质是双向链表,查找它的首部和尾部,时间复杂度 O(1),如果此时最末尾的数据也满了,那创建个新的页就好。

如果bb,上次 id=12111111,这次 id=343435455,那么为了让新加入数据后 B+ 树的叶子节点海涅那个保持有序,那么就需要旺叶子节点的中间找,查找的时间复杂度是 O(lgn),如果这个页满了,那就需要进行页分裂,并且页分裂的操作是需要加悲观锁的。

所以,我们一般都建议把主键设置成自增,这样可以提高效率,提高性能

那什么情况下不设置主键自增

mysql分库分表下的id**

在分库分表的情况下,插入的 id 都是专门的 id 服务生成的,如果要严格按照自增的话,那么一般就会通过 redis 来生成,按批次去获得,比如一次性获取几百个,用完了再去获取,但是如果 redis 服务挂了,功能就完全没法用了,那有么有不依赖与第三方组件的方法呢?

雪花算法

使用时间戳+机器码+流水号,一个字段实现了时间顺序、机器编码、创建时间。去中心化,方便排序,随便多表多库复制,并可抽取出生成时间,雪花ID主要是用在数据库集群上,去中心化,ID不会冲突又能相对排序。

总结

一般情况下,我们不推荐使用 UUID 来作为数据库的主键,只有分库分表的时候,才建议使用 UUID 来作为主键。

大学C语言、Java、数据结构、离散数学答案+几十本编程电子书 ,免费分享

链接:https://pan.baidu.com/s/1ES7FZxY-Gi_ZvEUE1-qgLg
提取码:75ol

标签:自增,分库,UUID,主键,Mysql,数据,id
From: https://www.cnblogs.com/songqwu/p/17991889

相关文章

  • 为什么不推荐用 UUID 作为 Mysql 的主键
    学习改变命运,技术铸就辉煌。大家好,我是銘,全栈开发程序员。UUID是什么我们先来了解一下UUID是什么?UUID是指UniversallyUniqueIdentifier,翻译为中文是通用唯一识别码,UUID的目的是让分布式系统中的所有元素都能有唯一的识别信息。如此一来,每个人都可以创建不与其它人冲突的UUI......
  • MySQL幻读问题
    幻读指的是一个事务开启之后,执行了两次相同的SELECT查询某一范围内的数据,但是第二次查询返回了第一次未返回的行,也就是读取到了幻行,这就是幻读问题。MySQL官方也将这个问题叫做幻象问题,读取到的行叫做幻行。地址:https://dev.mysql.com/doc/refman/8.0/en/innodb-next-key-lo......
  • 2、【实操】dash库设计web界面对mysql数据进行展示
    dash+mysql的简单应用python库简介:  dash:web界面的UI设计;  pymysql:MySQL数据库连接、操作引擎pandas:使用read.sql("sql",mysql_connection)函数将msyql的表单数据转换成DataFrame格式 第一步:  实现对MySQL数据库的连接,并对表单的数据进行展示    ......
  • Dos命令 Mysql数据定时备份和删除7前的文件
    一、dos 命令Mysql 数据本地和异地备份@echooff::以下1~8参数请按自己的情况修改;其他的不需要修改::=======================视各环境情况修改=================::1,备份目标主机setdbhost=127.0.0.1::2,数据库端口setdbport=3306::3,本地MYSQL的bin路径setmysq......
  • MySQL 运算符
    本章节我们主要介绍MySQL的运算符及运算符的优先级。MySQL主要有以下几种运算符:算术运算符MySQL支持的算术运算符包括:运算符 作用加法– 减法乘法/或DIV 除法%或MOD 取余在除法运算和模运算中,如果除数为0,将是非法除数,返回结果为NULL。1、加mysql>select......
  • MySQL 处理重复数据
    有些MySQL数据表中可能存在重复的记录,有些情况我们允许重复数据的存在,但有时候我们也需要删除这些重复的数据。本章节我们将为大家介绍如何防止数据表出现重复数据及如何删除数据表中的重复数据。防止表中出现重复数据你可以在MySQL数据表中设置指定的字段为PRIMARYKEY(主......
  • MySQL 序列使用AUTO_INCREMENT
    MySQL序列是一组整数:1,2,3,…,由于一张数据表只能有一个字段自增主键,如果你想实现其他字段也实现自动增加,就可以使用MySQL序列来实现。本章我们将介绍如何使用MySQL的序列。使用AUTO_INCREMENTMySQL中最简单使用序列的方法就是使用MySQLAUTO_INCREMENT来定义列。实例......
  • MySQL 8 版本升级
    升级过程中,安装一个新版本的MySQL版本可能需要升级以下这些内容:mysqlschema。mysql库中的表主要分成两类:数据字典表,即存储数据库对象元数据;系统表,即存储非数据字典表,用于其它操作用途其它schema。内嵌的(比如performance_schema、information_schema、ndbinfo、sys)或用户......
  • MySQL给表取别名,怎么才能不直接在sql中写出全部的字段
    资料来源官网教程问题<select>selectt1.id,t1.username,t1.password,t2.id,t2.username,t2.passwordfromsome_table1t1,some_table2t2....</select>如果字段很多一个一个写就很烦。在sql标签中,可以使用${XXX}占位符取别名<sqlid="us......
  • 作者推荐 | 【深入浅出MySQL】「底层原理」探秘缓冲池的核心奥秘,揭示终极洞察
    缓存池BufferPool机制应用系统分层架构:一个优化策略是将最常访问的数据存放在缓存中,以加快数据访问速度,避免频繁地访问数据库。操作系统:借助缓冲池机制来优化数据访问,从而避免了反复直接访问磁盘的开销,极大地提升了数据访问的速度。缓冲池通过在内存中临时存储最常访问的数据,将频繁......