在MySQL中有一个UUID () 函数,通常用UUID做唯一标识,需要在数据库中进行存储。使用此函数可以让MySQL生成一个UUID值,并以VARCHAR(36)类型的可读形式返回。如图1:

图1

UUID值是非常随机的,因此常常被用来当做主键值(PRIMARY KEY),而且这些以UUID作为主键的数据可以很容易的从不同的数据库中汇聚到一起。但是对于像MySQL的InnoDB存储引擎来说,使用UUID作为主键(PRIMARY KEY)会带来一些问题。

1、问题阐述

问题一:UUID的长度问题

UUID的长度为36个字符。假设数据库的字符集为UTF8,那么UUID的最大长度为2+3*26=110字节。如果这样的UUID作为主键的话,不仅会是主键的尺寸很大,而且会使二级索引的尺寸变大,原因是MySQL中的二级索引的value存的是PRIMARY KEY。由于主键和二级索引的尺寸很大,所以不利于在内存中操作

问题二:UUID的格式问题

MySQL的UUID ()使用的是version 1的UUID,该类型的UUID的特点是基于时间,它是一个128位的数字,由5个十六进制数字组成的utf8字符串表示,我们以图1中的UUID值为例:

432a4ec8-3642-11e9-805a-0050568238b5,每对字符实际上是一个在00-FF范围内的十六进制数; 总共有16个数字,前三个数字432a4ec8-3642-11e9是由时间戳生成。但是,最左边的组变化最快(每微秒10次)。我们可以验证,如图2

图2

因为UUID是不连续的随机数,所以insert操作是随机的,数据被离散存储,造成innodb频繁的页分裂,使得insert的操作十分低效。

2、结合问题定制方案

既然UUID作为主键带有这样那样的问题,难道说让我们在设计表结构时要放弃使用UUID吗?答案是否定的。我们可以通过采用binary(16)数据类型和重新安排UUID的顺序来解决之前提到的两个问题。

首先,BINARY(16) 这个二进制形式数据类型使用16个字节,比人类可读形式(“文本”形式)使用的VARCHAR(36)小的多。注意:只是二进制!没有字符集,没有排序,只有十六个字节。也许在某些应用程序中,文本形式仍然是必需的。那么我们可以使用虚拟列(MySQL5.7的新特性,虚拟列不占用存储空间)来存放文本形式的UUID。

然后,还有如何巧妙地重新排列二进制形式的字节的问题。我们在之前的问题二中已经了解到,MySQL的UUID()使用version1,最左边三个以破折号分隔的组是8字节的时间戳,最左边的第一组是时间戳的低四个字节; 第二组是中间两个字节时间戳,第三组是两个字节的高位时间戳,最左边的第一组变化最快。

因此,在我们存储UUID之前,重新安排UUID,使得快速变化的部分放到最后,例如:

把432a4ec8-3642-11e9-805a-0050568238b5重组为11e9-3642-432a4ec8-805a-0050568238b5

这种结构比起之前的结构更容易被cache缓存,同时存储上会更加连续。

3、方案验证

1)创建两张表

– 使用原生的uuid作为主键

create table test_uuid (id_binvarchar(36) PRIMARY KEY, name varchar(200)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

– 使用重组后的uuid做为主键

create table test_uuid_ordered (id_bin binary(16) PRIMARY KEY, name varchar(200)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2)在mysql中创建转换函数uuidtobin

DELIMITER //

CREATE FUNCTION uuidtobin(_uuid varchar(36))

RETURNS BINARY(16)

LANGUAGE SQL DETERMINISTIC CONTAINS SQL SQL SECURITY INVOKER

RETURN

UNHEX(CONCAT(

SUBSTR(_uuid, 15, 4),

SUBSTR(_uuid, 10, 4),

SUBSTR(_uuid, 1, 8),

SUBSTR(_uuid, 20, 4),

SUBSTR(_uuid, 25) ));

//

DELIMITER ;

3)编写执行测试程序,分别使用uuid()写入数据到test_uuid中和调用函数uuidtobin(UUID())写入数据到test_uuid_ordered中,一次插入1万行数据到相应的表中

4)测试结果

数据尺寸

横轴-插入次数 x 10,000

纵轴-数据文件尺寸(单位MB)

UUID表的用varchar(36)存储的文件大小几乎比有序UUID表用BINARY(16)存储的文件大45%

实际处理时间

横轴-插入次数 x 10,000

纵轴-实际时间(单位 秒)

5)最后添加虚拟列id_text存放“未重新排列”的顺序的UUID文本,可以方便将文本格式用于一些错误日志记录,调试等。

alter table test_uuid_ordered add

id_text varchar(36) generated always as

(

insert(

insert(

insert(

insert(

hex(

concat(substr(id_bin,5,4),substr(id_bin,3,2),

substr(id_bin,1,2),substr(id_bin,9,8))

),

9,0,'-'),

14,0,'-'),

19,0,’-’),

24,0,’-’)

) virtual;

原文链接

http://rdc.hundsun.com/portal/article/953.html

服务推荐

代理ip

蜻蜓代理

微信域名拦截检测

微信域名检测api

微信域名拦截检测

mysql用18位存储uuid_MySQL中存储UUID的最佳实践相关推荐

  1. mysql 存储uuid_MySQL中存储UUID的最佳实践

    在 MySQL 中有一个UUID () 函数, 通常用UUID做唯一标识,需要在 数据库 中进行存储. 使用此函数可以让MySQL生成一个UUID值,并以VARCHAR(36)类型的可读形式返回.如图 ...

  2. 《大话存储__网络存储系原理精解与最佳实践》电子书下载

    大话存储__网络存储系原理精解与最佳实践,经典图书   网络存储,是近二十年来的新兴行业.从纸带到硬盘再到大型磁盘阵列,存储系统经历了从简单到复杂,从单块硬盘到存储区域网络(SAN).网络存储行业目前 ...

  3. 在ASP.NET Web API中返回错误的最佳实践

    本文翻译自:Best practice to return errors in ASP.NET Web API I have concerns on the way that we returns e ...

  4. Java 中处理 Exception 的最佳实践

    Java 中处理 Exception 的最佳实践 在Java中处理异常并不是一个简单的事情.不仅仅初学者很难理解,即使一些有经验的开发者也需要花费很多时间来思考如何处理异常,包括需要处理哪些异常,怎样 ...

  5. mysql 营业时间_mysql – 在数据库中存储各种商店开放时间的方法

    我想在数据库中存储不同商店的营业时间.目前我正在使用最简单的解决方案: CREATE TABLE opening_times( shop_id int(3) NOT NULL, times varch ...

  6. mysql获取18位和15位身份证号中的出生日期、年龄

    18位身份证号码 select cast(substring(idno,7,8) as date) as 出生日期,2022-substring(idno,7,4) as age from table ...

  7. 关于Azure存储账户中存储虚拟机VHD文件的注意事项

     Joy Qiao from MSFT  Thu, Mar 12 2015 3:16 PM 我们在使用Azure时经常都会在Azure存储账户中放一些文件,包括Azure虚机的VHD文件也都是放在存储 ...

  8. 数据库周刊62丨央企2021年数据库成交公告,国产占90%;流数据库HStreamDB开源;MySQL主从双写导致数据丢失;Oracle 19c升级最佳实践;PG日常工作分享;MySQL MGR运维指

    热门资讯 [1.中央国家机关2021年数据库成交公告:国产数据库份额占90% [摘要]据央采网3月19日发布的<中央国家机关2021年数据库软件协议供货采购项目成交公告>显示事务型数据库管 ...

  9. boot jpa mysql postman spring_听说过spring-data-jdbc么?来个最佳实践

    本文的完整示例代码,见github仓库.小q只在文中介绍最关键的代码块. https://github.com/yuanluoji/purestart-springboot-data-jdbc 很多人 ...

最新文章

  1. 解决数据库读写分离(转)
  2. 超全超实用的Javascript类库和jQuery插件大全之一:图片,地图和图形
  3. python多久学会自学-零基础自学Python多久可以找工作?
  4. 一句话介绍区块链是什么
  5. 打破技术型思维:产品经理的门槛在门里面
  6. 成都Uber优步司机奖励政策(4月24日)
  7. common lisp 学习第三天 函数、注释
  8. Linux系统添加永久静态路由的方法
  9. 应届生还是研究生?与大学生的MSN谈话二
  10. 51单片机按键控制数码管0~9_0.39寸2位数码管厂家
  11. oracle讲表通过主键去重,数据库试题,数据库基础试题及答案
  12. Win10,Office2016及以上图标异常解决方案
  13. 0504-android-云知声sdk使用
  14. (滁院20级计科专用)期末考试复习-操作系统
  15. html2canvas官网blurry,Why html2canvas produced blurry pdf file?
  16. 骞云科技携手 EMC,联袂打造超融合基础架构云管方案
  17. -webkit-tap-highlight-color
  18. gets() 与puts()的用法
  19. 幼儿园教师怎么教计算机知识,幼儿园教师的常识教案大全
  20. python文本聚类_python 文本聚类算法

热门文章

  1. AirDisk产品Q3C两大功能
  2. VS Code插件 使用 VS Code 连接 MySQL 数据库
  3. 年薪达 35 万元,杭州成为薪酬最高的城市,北上、重庆通勤时间最久,揭晓 2022 年最具潜力的软件名城!...
  4. 使用getParameterValues方法接收参数的两种方法
  5. apk自动升级,高于android N自动安装不弹框的问题解决
  6. 基于Solidworks的三维光路结构示意图绘制实例演示
  7. 安装mysql卡在等待页面_MySQL安装到最后一步未响应的五种解决方法
  8. 用余弦定理求三角形内角
  9. struts1框架基本(笔记)
  10. ssm上传文件进度条_SSM框架+Plupload实现分块上传大文件示例