数据库主键设计
2018-12-18 本文已影响48人
良人与我
先来一个测,看看主键长度对查询和插入性能的影响。
两个表
t_book 主键是string 长度 36 字节
t_student 主键是bigint 8字节
CREATE TABLE `t_book` (
`book_id` varchar(36) NOT NULL,
`book_desc` varchar(255) DEFAULT NULL,
`book_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`book_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `t_student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`create_time` datetime DEFAULT NULL,
`sname` varchar(255) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1000001 DEFAULT CHARSET=utf8mb4;
通过程序每个表插入 100w 条数据
t_book 花费的时间是 t_student 的十倍以上
(已经有100W 再通过程序每次插入1,连续100次。 t_book 花费 35分钟,t_student 花费4分钟)
再看看 查询 count(*) 的性能
SELECT count() from t_book
query time 3.187s
SELECT count() from t_student
query time 0.274s
差距在10倍以上
数据是200W时候
SELECT count() from t_book
query time 7.056s
SELECT count() from t_student
query time 0.556s
差距依然在10倍以上
插入速度慢原因
因为插入时候主键的生成策略用的是 uuid
因为是无序的,所以每次索引生成时候需要重排序,浪费时间。
查询速度慢原因
查询connt(*)时候,需要将索引读入到内存中。
如果索引长度越长,同样多的索引需要存储的磁盘空间越大。磁盘IO 也是系统中最大的瓶颈。导致整个性能下降。
所以考虑到性能,主键最好是 递增的并且占用存储空间小。
单表情况
可以是 long 型, 自增主键。
分表情况
需要一个id 生成器。
timestemp + 序列号 + 机器号 组成的 数字
需要保证时间不能回滚,否则会出现重复的id