参考博客:https://www.cnblogs.com/wyq178/p/12548864.html

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

1.使用自增的内部结构

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

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

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

2.使用uuid的索引内部结构

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

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

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

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

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

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

3.自增id的缺点

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

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

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

  3. Auto_Increment锁机制会造成自增锁的抢夺,有一定的性能损失

附:Auto_increment的锁争抢问题,如果要改善需要调优innodb_autoinc_lock_mode的配置

MySQL学习(十一)为什么不推荐使用uuid和雪花id的更多相关文章

  1. 深入分析mysql为什么不推荐使用uuid或者雪花id作为主键

    前言:在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建 ...

  2. MySQL学习(十一)

    MySQL的函数 1 数学函数 2 字符串函数 3 日期和时间函数 4 条件判断函数 5 系统信息函数 6 加密解密函数 7 其他函数 2 字符串函数 length计算的是字节长度 char_leng ...

  3. 为什么MySQL不推荐使用uuid作为主键?

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

  4. 我的MYSQL学习心得(十一) 视图

    我的MYSQL学习心得(十一) 视图 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  5. 我的MYSQL学习心得(十一)

    原文:我的MYSQL学习心得(十一) 我的MYSQL学习心得(十一) 我的MYSQL学习心得(一) 我的MYSQL学习心得(二) 我的MYSQL学习心得(三) 我的MYSQL学习心得(四) 我的MYS ...

  6. 我的MYSQL学习心得(六) 函数

    我的MYSQL学习心得(六) 函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  7. 我的MYSQL学习心得(十七) 复制

    我的MYSQL学习心得(十七) 复制 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  8. Mysql 学习1

      Mysql学习   一.数据库   1 数据库概念(了解) 1.1 什么是数据库 数据库就是用来存储和管理数据的仓库! 数据库存储数据的优先: 可存储大量数据: 方便检索: 保持数据的一致性.完整 ...

  9. mysql basic operation,mysql总结,对mysql经常使用语句的详细总结,MySQL学习笔记

    mysql> select * from wifi_data where dev_id like "0023-AABBCCCCBBAA" ; 1.显示数据库列表.show d ...

  10. MySQL学习(4)---MySQL索引

    ps:没有特殊说明,此随笔中默认采用innoDB存储引擎中的索引,且索引都是指B+树(多路平衡搜索树)结构组织的索引.其中聚集索引.复合索引.前缀索引.唯一索引默认都是使用B+树,统称为索引. 索引概 ...

随机推荐

  1. kubernetes中 flannel网络组件

    Flannel 软件包地址:https://github.com/coreos/flannel Flannel是CoreOS开源的CNI网络插件,下图flannel官网提供的一个数据包经过封包.传输以 ...

  2. Chrome 中设置默认搜索引擎为 google.com

    https://google.com/search?q=%s&ref=opensearch&safe=off 那么就可以使搜索结果默认在新标签页打开,同时关闭了搜索结果的安全过滤.   ...

  3. 040_Field Set

    Field Set是一组字段.例如,您可以有一个Field Set,其中包含描述用户的名字,中间名,姓氏和业务标题的字段.将Field Set添加到Visualforce页面时,开发人员可以遍历字段并 ...

  4. windows 系统的端口问题

    netstat -ano 列出所有正在使用的端口netstat -aon|findstr "4300" 查询占用该端口的PIDtasklist|findstr "4464 ...

  5. Ribbit Mq 实现延迟消息

    --------------------好记性不如烂笔头--------------------------- windows 环境,使用 rabbit Mq 需要安装, erl   和  rabbi ...

  6. Java基础学习:2、Java数据类型及逻辑运算符

    1.数据类型: 数据类型范围: byte:-2^7 ~ 2^7-1,即-128 ~ 127.1字节.Byte.末尾加B short:-2^15 ~ 2^15-1,即-32768 ~ 32767.2字节 ...

  7. 微信小程序云函数中管理短信验证码的完整SDK工具

    微信小程序云开发管理短信验证码并不是一件容易的事情,它不像其他web服务器开发中可以将验证码存放到session或者cookie中,你只能将其存到云开发的数据库中,实现起来非常困难.一个简单的需要短信 ...

  8. flutter 底部导航栏 BottomNavigationBar

    话不多说,上代码 import 'package:flutter/material.dart'; import 'package:flutter_zhihu/pages/tabs/homeTab.da ...

  9. Number(数字)

    Python 中的变量不需要声明.每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建. 在 Python 中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对 ...

  10. 使用@Param注解时注意org.springframework.data.repository.query.Param与org.apache.ibatis.annotations.Param的区别

    注解@Param有以下两种: 1.Spring org.springframework.data.repository.query.Param 2.mybatis org.apache.ibatis. ...