MySQL创立表的时候能够不设置主键吗?
MySQL创立表的时候是能够不被动设置主键的,然而表是肯定须要一个主键的,MySQL会被动将第一个不为null的惟一索引设置为主键

为什么MySQL举荐应用自增id作为主键?
MySQL官网举荐不要应用uuid或者不间断不反复的雪花作为主键,而是应用间断自增的主键id
应用自增id的内部结构
自增id的值是程序的,所以innodb在索引B+树的叶子节点层面能够间接把每一条记录都存储在上一条记录的前面,当达到页面的最大填充因子的时候(页面容量曾经满了)下一条记录就会写入新的页中,数据依照这种程序的形式进行填充,主键页就会以近乎于程序的记录填满,晋升了页面的最大填充率,不会有页的节约
新插入的行肯定会在原有的最大数据的下一行,这样MySQL定位和寻址十分快,不会因为计算而做出额定的耗费,
并且可能缩小页决裂和碎片的产生
页决裂:保障后一个数据页的所有行主键值比前一个数据页的主键值大,所以当ID不为自增的主键的时候,就会导致后一个页的所有行并不一定比前一个数据页的行的id大。这时就会触发页决裂的逻辑,对两个页之间的数据进行调整,底层就是树结构的调整,这个耗费是很大的,甚至会波及到多个数据页,导致性能升高
应用自增id的毛病

  1. 他人一旦爬取你的数据库,就能够依据数据库的自增id获取到你业务的增长信息,从而剖析出经营状况
  2. 对于高并发的负载,innodb在依照主键进行插入的时候会造成显著的锁争用,auto_increment锁机制会造成自增锁的抢夺,有肯定的性能损失
    为什么分布式系统不必自增id,而是要用雪花算法生成id
    分布式id创立的业务需要
  3. 全局惟一
  4. 趋势递增 innodb引擎的叶子结点是有序的双向链表,趋势递增能够减少性能,不会打乱树的构造
  5. 信息安全
  6. 最好蕴含工夫戳
    为什么自增id不适宜分布式系统?
    当数据宏大的时候,在数据库分库分表之后,数据库自增id不能满足惟一id来示意数据;因为每个表都依照本人的节奏自增,会造成id抵触,从而无奈满足需要
    应用auto_increment实现便宜的分布式惟一主键
    flickr有相似的计划,构建是一个专用的数据库服务器,下面只有一个数据库,在数据库外面有用于32位id和64位id的id表,id是auto自增的,所有数据库生成id都会向这个服务器发申请,而后服务器散发id上来,也能达到一种分布式惟一主键的成果
    相似于session-redis的思维,把所有的sessionid都存在redis外面,所有的服务器实例在比拟cookie的时候就先去redis外面比拟,这样就能防止因为负载平衡导致的cookie生效问题
    当然这个便宜的做法显然是有很大问题的
  7. 并发量很小,因为只有一台服务器
  8. 减少开销,并且整个申请流程变慢,因为须要向服务器发申请,并且是在硬盘层面进行操作的
  9. flickr服务器成了整个零碎的瓶颈和隐患,如果服务器宕机整个零碎间接崩掉了
    雪花算法
    是twitter开源的分布式id生成算法,后果是一个64位的longint类型,核心思想是用41位来作为工夫戳,10位来作为机器的id,12位作为毫秒内的流水号(意味着每个节点能够在每毫秒生成4096个id),最初还有一个符号为永远为0
    长处
    ● 齐全在内存生成,高性能高可用
    ● 容量大,每秒能够生成几百万id
    ● 趋势递增,插入数据库索引树的时候,性能比拟高
    毛病
    ● 依赖零碎时钟的一致性,如果某台机器的零碎时钟回拨,有可能造成id抵触
    ● 多台机器的ID只能保障趋势减少,即每一台机器都能保障这台机器生成的ID是在减少的,然而多台机器并不一定相对递增
    ● 41位工夫戳只能保障69年无反复ID
    ● 因为是64位的ID,在传递给前端的时候须要用字符串的类型进行传递,因为js的number类型最大只反对53位
    其余分布式ID计划
    ● UUID:JAVA自带的API,生成一个唯一性的字符串,不能保障有序递增
    ● UidGenerator:百度开源的分布式ID生成器,基于雪花算法
    ● Leaf:美团开源的分布式ID生成器,能保障全局惟一,趋势递增,然而须要依赖关系数据库、Zookeeper等中间件

本文由mdnice多平台公布