前言:在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究竟有什么坏处?本篇博客我们就来分析这个问题,探讨一下内部的原因。

一:mysql和程序实例

1.1:要说明这个问题,我们首先来建立三张表,分别是user_auto_key,user_uuid,user_random_key,分别表示自动增长的主键,uuid作为主键,随机key作为主键,其它我们完全保持不变.根据控制变量法,我们只把每个表的主键使用不同的策略生成,而其他的字段完全一样,然后测试一下表的插入速度和查询速度:

注:这里的随机key其实是指用雪花算法算出来的前后不连续不重复无规律的id:一串18位长度的long值

id自动生成表:

用户uuid表

随机主键表:

1.2:光有理论不行,直接上程序,使用spring的jdbcTemplate来实现增查测试:

技术框架:springboot+jdbcTemplate+junit+hutool,程序的原理就是连接自己的测试数据库,然后在相同的环境下写入同等数量的数据,来分析一下insert插入的时间来进行综合其效率,为了做到最真实的效果,所有的数据采用随机生成,比如名字、邮箱、地址都是随机生成,程序已上传自gitee,地址在文底。

package com.wyq.mysqldemo;
import cn.hutool.core.collection.CollectionUtil;
import com.wyq.mysqldemo.databaseobject.UserKeyAuto;
import com.wyq.mysqldemo.databaseobject.UserKeyRandom;
import com.wyq.mysqldemo.databaseobject.UserKeyUUID;
import com.wyq.mysqldemo.diffkeytest.AutoKeyTableService;
import com.wyq.mysqldemo.diffkeytest.RandomKeyTableService;
import com.wyq.mysqldemo.diffkeytest.UUIDKeyTableService;
import com.wyq.mysqldemo.util.JdbcTemplateService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.StopWatch;
import java.util.List;
@SpringBootTest
class MysqlDemoApplicationTests {@Autowiredprivate JdbcTemplateService jdbcTemplateService;@Autowiredprivate AutoKeyTableService autoKeyTableService;@Autowiredprivate UUIDKeyTableService uuidKeyTableService;@Autowiredprivate RandomKeyTableService randomKeyTableService;@Testvoid testDBTime() {StopWatch stopwatch = new StopWatch("执行sql时间消耗");/*** auto_increment key任务*/final String insertSql = "INSERT INTO user_key_auto(user_id,user_name,sex,address,city,email,state) VALUES(?,?,?,?,?,?,?)";List<UserKeyAuto> insertData = autoKeyTableService.getInsertData();stopwatch.start("自动生成key表任务开始");long start1 = System.currentTimeMillis();if (CollectionUtil.isNotEmpty(insertData)) {boolean insertResult = jdbcTemplateService.insert(insertSql, insertData, false);System.out.println(insertResult);}long end1 = System.currentTimeMillis();System.out.println("auto key消耗的时间:" + (end1 - start1));stopwatch.stop();/*** uudID的key*/final String insertSql2 = "INSERT INTO user_uuid(id,user_id,user_name,sex,address,city,email,state) VALUES(?,?,?,?,?,?,?,?)";List<UserKeyUUID> insertData2 = uuidKeyTableService.getInsertData();stopwatch.start("UUID的key表任务开始");long begin = System.currentTimeMillis();if (CollectionUtil.isNotEmpty(insertData)) {boolean insertResult = jdbcTemplateService.insert(insertSql2, insertData2, true);System.out.println(insertResult);}long over = System.currentTimeMillis();System.out.println("UUID key消耗的时间:" + (over - begin));stopwatch.stop();/*** 随机的long值key*/final String insertSql3 = "INSERT INTO user_random_key(id,user_id,user_name,sex,address,city,email,state) VALUES(?,?,?,?,?,?,?,?)";List<UserKeyRandom> insertData3 = randomKeyTableService.getInsertData();stopwatch.start("随机的long值key表任务开始");Long start = System.currentTimeMillis();if (CollectionUtil.isNotEmpty(insertData)) {boolean insertResult = jdbcTemplateService.insert(insertSql3, insertData3, true);System.out.println(insertResult);}Long end = System.currentTimeMillis();System.out.println("随机key任务消耗时间:" + (end - start));stopwatch.stop();String result = stopwatch.prettyPrint();System.out.println(result);}

1.3:程序写入结果

user_key_auto写入结果:

user_random_key写入结果:

user_uuid表写入结果:

1.4:效率测试结果

在已有数据量为130W的时候:我们再来测试一下插入10w数据,看看会有什么结果:

可以看出在数据量100W左右的时候,uuid的插入效率垫底,并且在后续增加了130W的数据,uudi的时间又直线下降。时间占用量总体可以打出的效率排名为:auto_key>random_key>uuid,uuid的效率最低,在数据量较大的情况下,效率直线下滑。那么为什么会出现这样的现象呢?带着疑问,我们来探讨一下这个问题:

二:使用uuid和自增id的索引结构对比

2.1:使用自增id的内部结构

自增的主键的值是顺序的,所以Innodb把每一条记录都存储在一条记录的后面。当达到页面的最大填充因子时候(innodb默认的最大填充因子是页大小的15/16,会留出1/16的空间留作以后的     修改):

①下一条记录就会写入新的页中,一旦数据按照这种顺序的方式加载,主键页就会近乎于顺序的记录填满,提升了页面的最大填充率,不会有页的浪费

②新插入的行一定会在原有的最大数据行下一行,mysql定位和寻址很快,不会为计算新行的位置而做出额外的消耗

③减少了页分裂和碎片的产生

2.2:使用uuid的索引内部结构

因为uuid相对顺序的自增id来说是毫无规律可言的,新行的值不一定要比之前的主键的值要大,所以innodb无法做到总是把新行插入到索引的最后,而是需要为新行寻找新的合适的位置从而来分配新的空间。这个过程需要做很多额外的操作,数据的毫无顺序会导致数据分布散乱,将会导致以下的问题:

①:写入的目标页很可能已经刷新到磁盘上并且从缓存上移除,或者还没有被加载到缓存中,innodb在插入之前不得不先找到并从磁盘读取目标页到内存中,这将导致大量的随机IO

:因为写入是乱序的,innodb不得不频繁的做页分裂操作,以便为新的行分配空间,页分裂导致移动大量的数据,一次插入最少需要修改三个页以上

:由于频繁的页分裂,页会变得稀疏并被不规则的填充,最终会导致数据会有碎片

在把随机值(uuid和雪花id)载入到聚簇索引(innodb默认的索引类型)以后,有时候会需要做一次OPTIMEIZE TABLE来重建表并优化页的填充,这将又需要一定的时间消耗。

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

2.3:使用自增id的缺点

那么使用自增的id就完全没有坏处了吗?并不是,自增id也会存在以下几点问题:

①:别人一旦爬取你的数据库,就可以根据数据库的自增id获取到你的业务增长信息,很容易分析出你的经营情况

②:对于高并发的负载,innodb在按主键进行插入的时候会造成明显的锁争用,主键的上界会成为争抢的热点,因为所有的插入都发生在这里,并发插入会导致间隙锁竞争

③:Auto_Increment锁机制会造成自增锁的抢夺,有一定的性能损失
附:Auto_increment的锁争抢问题,如果要改善需要调优innodb_autoinc_lock_mode的配置

三:总结

本篇博客首先从开篇的提出问题,建表到使用jdbcTemplate去测试不同id的生成策略在大数据量的数据插入表现,然后分析了id的机制不同在mysql的索引结构以及优缺点,深入的解释了为何uuid和随机不重复id在数据插入中的性能损耗,详细的解释了这个问题。在实际的开发中还是根据mysql的官方推荐最好使用自增id,mysql博大精深,内部还有很多值得优化的点需要我们学习。

最后

技术是没有终点的,也是学不完的,最重要的是活着、不秃。零基础入门的时候看书还是看视频,我觉得成年人,何必做选择题呢,两个都要。喜欢看书就看书,喜欢看视频就看视频。最重要的是在自学的过程中,一定不要眼高手低,要实战,把学到的技术投入到项目当中,解决问题,之后进一步锤炼自己的技术。

技术学到手后,就要开始准备面试了,找工作的时候一定要好好准备简历,毕竟简历是找工作的敲门砖,还有就是要多做面试题,复习巩固。有需要面试题资料的朋友点击这里可以免费领取。


当中,解决问题,之后进一步锤炼自己的技术。

技术学到手后,就要开始准备面试了,找工作的时候一定要好好准备简历,毕竟简历是找工作的敲门砖,还有就是要多做面试题,复习巩固。有需要面试题资料的朋友点击这里可以免费领取。

[外链图片转存中…(img-EmncGH4A-1627107371997)]

web开发重点,html5培训机构相关推荐

  1. Web开发:HTML5、CSS、JavaScript必备教程

    2019独角兽企业重金招聘Python工程师标准>>> Web开发:HTML5.CSS.JavaScript必备教程 想开启Web开发的智慧之门吗?想DIY炫酷的网页特效设计吗?想通 ...

  2. 学python开发-天津python培训机构多少钱

    为什么学Python 人工智能已经上升到国家发展战略,机器学习和深度学习这些词汇大量的出现在网络流行语中,人脸识别以及自动驾驶已经在现实中开始引用了,某种意义上人工智能好像走在我们的生活了,我们身处在 ...

  3. HTML5的web开发,基于Html5技术的WEB开发

    摘 要:HTML是互联网上应用最广泛的语言,得到了业界大力支持,已经成为WEB发展的标准.它强大了对多媒体的支持力度和远程与本地对数据的处理能力,本文对HTML5的新特性进行了总结,分析了该语言在移动 ...

  4. web前端开发示例_40多个针对Web开发人员HTML5教程和示例

    web前端开发示例 HTML 5 offers a lot of new features to help web developers. In the last few days, I have r ...

  5. 前端开发如何选择培训机构

    随着互联网科技与5G技术的不断发展与落实,市场上出现了更多的新场景需要开发.因此,各大企业对前端开发技术人才的需求量逐渐增加.目前相关前端开发的岗位在逐渐的增多,这也就意味着前端开发的就业前景是比较好 ...

  6. html去除边角,WEB开发向HTML5及CSS3迈进(1)——圆框边角的处理

    web页面中,对于圆角边框处理时会增加许多不必要的html代码,这对于内容的表述来说是非常不和谐的.一片有逻辑结构的内容中增加了这些代码,一眼望去就像草地上的杂草一样的星星点点.对于如今已向CSS3开 ...

  7. 自学也能学得会的《零基础入门学习Web开发》(HTML5 CSS3)

    1 Web开发是什么 很多读者可能还不明白,Web开发到底是什么. 其实,我们所说的Web开发通常相当于前端开发与后端开发的组合. 前端开发主要通过HTML.CSS.JavaScript. AJAX. ...

  8. 培训机构要不要去 适合谁去

    今天来说说 "培训机构" 标题很简洁,不要说我标题党,虽说我估计已经有小编的潜质. 写这篇文章的原因 因为说到这个话题,我更多的是心痛和无奈.真的,不矫情的说,这是很多我的读者和粉 ...

  9. 培训机构要不要去?适合谁去

    今天来说说 "培训机构" 标题很简洁,不要说我标题党,虽说我估计已经有小编的潜质. 写这篇文章的原因 因为说到这个话题,我更多的是心痛和无奈.真的,不矫情的说,这是很多我的读者和粉 ...

最新文章

  1. xmarin.android导航栏,android – 如何在xamarin表单中更改导航页面后退按钮
  2. 给UIScrollView添加category实现UIScrollView的轮播效果
  3. 远程SSH连接服务与基本排错
  4. MFC中绘制高亮的图标 VC图标填充半透明色
  5. python 图片转视频ffmpeg_python图片转视频(opencv),ffmpeg压缩视频
  6. hadoop伪分布式配置
  7. datetime 索引_MySQL 性能优化:MySQL 中的隐式转换造成的索引失效
  8. linux7网卡启动的过程,linux网络启动
  9. read命令_dbatools Read-DbaBackupHeader命令的便捷功能
  10. NPM 简单实用说明
  11. html怎么自动过度,HTML与CSS中的过渡模块
  12. Leetcode 惊现马化腾每天刷题 ? 为啥大佬都这么努力!
  13. mflac格式解密_mflac格式是什么意思
  14. 饥荒服务器物品指令,饥荒控制台指令大全物品大全服务器管理命令大全.docx
  15. 服务器打包文件工具,项目增量发版之全自动打包流程(patch-generator-desk打包软件)...
  16. Unirech阿里云国际站轻量应用服务器简介
  17. Android单元测试 Instrumentation
  18. PyTorch神经网络基础
  19. 微信公众号官方文档入口
  20. UE5 关闭编辑器后C++类从内容浏览器中消失

热门文章

  1. 单片机c语言常用指令,单片机C语言(C51)的常用库函数.doc
  2. echars 柱状图靠左_echart 柱状图如何让y轴文字靠左显示,series上文字右对齐显示...
  3. 为何选择年前加盟vr全景项目?有你想不到的优势
  4. 远场语音技术简介-001
  5. 写一个激光入门培训材料
  6. Embedding层
  7. AtCoder Beginner Contest 297——A-E题讲解
  8. 达梦数据库通过DBLINK访问ORACLE (从DM到ORACLE)
  9. oracle contains
  10. java string转int 异常_Java中String转int型的方法以及错误处理