业务 Key 往往比较长,所占空间更大,导致更大的磁盘 IO
在 Key 确定前不能持久化数据,有时我们没有在确定数据 Key 时,就想先添加一条记录,之后再更新业务 Key
设计一个兼具易用和性能的 Key 生成方案比较难
逻辑 Key 的优点
不会因为业务的变动而需要修改 Key 逻辑
操作简单,且易于管理
逻辑 Key 往往更小,性能更优
逻辑 Key 更容易保证唯一性
更易于优化
逻辑 Key 缺点
查询主键列和主键索引需要额外的磁盘空间
在插入数据和更新数据时需要额外的 IO
更多的 join 可能
如果没有唯一性策略限制,容易出现重复的 Key
测试环境和正式环境 Key 不一致,不利于排查问题
Key 的值没有和数据关联,不符合三范式
不能用于搜索关键字
依赖不同数据库系统的具体实现,不利于底层数据库的替换
五、主键生成
一般情况下,我们都使用 Mysql 的自增 ID,来作为表的主键,这样简单,而且从上面讲到的来看,性能也是最好的。但是在分库分表的情况情况下,自增 ID 则不能满足需求。我们可以来看看不同数据库生成 ID 的方式,也看一些分布式 ID 生成方案。利于我们思考甚至实现自己的分布式 ID 生成服务。
数据库的实现
Mysql 自增
Mysql 在内存中维护一个自增计数器,每次访问 auto-increment 计数器的时候, InnoDB 都会加上一个名为AUTO-INC 锁直到该语句结束(注意锁只持有到语句结束,不是事务结束)。AUTO-INC 锁是一个特殊的表级别的锁,用来提升包含 auto_increment 列的并发插入性。
在分布式的情况下,其实可以独立一个服务和数据库来做 id 生成,依旧依赖 Mysql 的表 id 自增能力来为第三方服务统一生成 id。为性能考虑可以不同业务使用不同的表。
Mongodb ObjectId
Mongodb 为防止主键冲突,设计了一个 ObjectId 作为主键 id。它由一个 12 字节的十六进制数字组成,其中包含以下几部分:
Time:时间戳。4 字节。秒级。
Machine:机器标识。3 字节。一般是机器主机名的散列值,这样就确保了不同主机生成不同的机器 hash 值,确保在分布式中不造成冲突,同一台机器的值相同。
PID:进程 ID。2 字节。上面的 Machine 是为了确保在不同机器产生的 objectId 不冲突,而 pid 就是为了在同一台机器不同的 mongodb 进程产生的 objectId 不冲突。
INC:自增计数器。3 字节。前面的九个字节保证了一秒内不同机器不同进程生成的 objectId 不冲突,自增计数器,用来确保在同一秒内产生的 objectId 也不会发现冲突,允许 256 的 3 次方等于 16777216 条记录的唯一性。
Cassandra TimeUUID
Cassandra 使用下面规则生成一个唯一的 id:time + MAC + sequence
方案
Zookeeper 自增:通过 zk 的自增机制实现。
Redis 自增:通过 Redis 的自增机制实现。
UUID:使用 UUID 字符串作为 Key。
snowflake 算法:和 Mongodb 的实现类似,1位符号位 + 41位时间戳(毫秒级)+ 10位数据机器位 + 12位毫秒内的序列。
开源实现
百度 UidGenerator:基于snowflake算法。
美团 Leaf:同时实现了基于 Mysql 自增(优化)和 snowflake 算法的机制。
以上就是MySQL 如何设计主键的详细内容,更多文章请关注木庄网络博客!
相关阅读 >>
详解mysql插入数据成功但是报[err] 1055错误如何解决
更多相关阅读请进入《mysql》频道 >>

数据库系统概念 第6版
本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。