关于自增主键和UUID的比较,能够从数据插入前,插入中,插入三个阶段进行比较,他们有各自的有点,固然也有各自的不足。下面就分三个阶段说说优缺点。mysql
1)UUID 须要手动维护,要求是保证每次生成的数据都是不一致的,而后咱们须要手写sql插入,若是代码逻辑中含有大量这种非业务相关的代码,实际上是很不友好的,因此尽可能透明。可是在代码中(Java)你能够在未插入以前就知道了主键ID,这个在有关联表须要插入时很是不错。sql
2)自增主键 插入前无需维护,编写的sql也不用管这个字段,数据库本身维护,对写程序来讲彻底透明。缺点就是插入前代码中(Java)并不知道主键。数据库
1)UUID 长度相对比较大,若是大批量数据插入,在网络传输间,实际上这个字段占用的空间是不容小觑的,固然通常的程序不会担忧这个,由于选用 Hibernate 的人,基本不会在意某个字段的事。另外,既然是主键那么必然要考虑主键的惟一性,如何作这个惟一的校验呢?尤为是并发状况下,若是有多个相同的键同时插入怎么办?因此我以为这里会有个锁(多是锁索引,也多是锁表),所以使用UUID并发插入确定会发生阻塞的。这个能够去试验一下,开两个事务,使用相同的ID插入,后一个插入确定会被阻塞,因此我以为这里确定有一个判断是否已经存在键的代码,并且是同步的,若是键存在那么阻塞后面的操做,固然初步判断不是锁表,若是是锁表会致使全部的插入阻塞,实际上不会。网络
2)自增主键 在插入时彻底没有流量,由于都是数据库自己维护,因此很干净。关于自增主键插入有很并发
多须要补充的知识,这里先从MySQL之前的版本提及,之前采用的是:对每一个含有自增加值的表都有一个自增加计数器(auto-increment counter),当有数据插入时就会执行操做:spa
select max(auto_inc_col) from t for update;线程
这个之前自增加字段锁的方式 AUTO-INC Locking,称为传统模式,他还有个很突出的特色是自增主键的值不用等待事务提交才生成,而是马上生效,因此必定程度上提升了并发效率。可是,对于并发插入或者 insert..select 这种大批量数据插入的方式都是会被阻塞的。索引
而后就出现了新的自增加锁方式,版本> MySQL 5.1.22开始,InnoDB提供了一种轻量级互斥的自增加实现机制,在内存中会有一个互斥量(mutex),每次分配自增加ID时,就经过估算插入的数量(前提是必须可以估算到插入的数量,不然仍是使用传统模式),而后更新mutex,下一个线程过来时重新 mutex 开始继续计算,这样就能避免传统模式非要等待每一个都插入以后才能获取下一个。这种实现方式是经过 innodb_autoinc_lock_mode 的来来肯定锁的方式。事务
我如今使用的 MySQL版本是 5.6.16 引擎是 innodb.内存
首先执行以下语句,检查数据库自增主键锁的模式(> MySQL 5.1.22 )
SHOW VARIABLES LIKE 'innodb_autoinc_lock_mode' 默认是 1
innodb_autoinc_lock_mode 有三个值分别是
0(traditional) ,这个就是以前说的 AUTO-INC Locking,并发相对较差
1(default consecutive),对不一样的插入操做会有不一样的方式,即传统方式、互斥方式
2(interleaved),彻底使用互斥方式,并发最好,可是缺点明显,大并发下可能会出现重复。
咱们只用考虑 innodb_autoinc_lock_mode = 1 的状况,另外两种是固定的模式,而连续模式究竟是使用传统仍是使用交叉模式,就是根据插入数据的量是否可估算的,先看看插入的分类:
Simple inserts
经过分析insert语句能够肯定插入数量的insert语句,
Bulk inserts
经过分析insert语句不能肯定插入数量的insert语句
Mixed-mode inserts
不肯定是否须要分配 auto_increment id
名称 | 插入语法 |
Insert-like | INSERT,INSERT … SELECT, REPLACE, REPLACE … SELECT, LOAD DATA, INSERT VALUES(),VALUES() |
Simple inserts | INSERT, INSERT … VALUES(),VALUES() |
Bulk inserts | INSERT … SELECT, REPLACE … SELECT, LOAD DATA |
Mixed-mode inserts | INSERT INTO t1 (c1,c2) VALUES (1,’a'), (NULL,’b'); INSERT … ON DUPLICATE KEY UPDATE |
总结:若是是连续模式,那么对 Simple inserts 采用的是互斥方式,若是是 Bulk inserts 采用的是传统模式,Mixed-mode inserts 模式其实也是使用互斥方式,可是缺点就是浪费大量的ID。
回到问题上,mysql 对自增主键作了不少特殊处理,因此在插入的并发状况下仍是能够接受的,固然相对UUID仍是差了点,毕竟只要UUID只要维护惟一性,然而自增主键首先要考虑生成规则,而后还要考虑惟一性,然而就是这个生成规则MySQL已经采用互斥方式进行了改进。
1)UUID 仍是长度的问题,这个影响的不只仅是磁盘空间问题,更多仍是索引的建立与查找,MySQL采用的 BTree+ 索引,并且主键都会附带在全部其余的索引的第一列(默认),首先致使索引空间变大,其次还会致使节点的分裂和移动,因此插入的时候由于须要维护索引更新,因此插入相对比较慢。另外UUID有一个很大的好处就是数据库合并,由于任何UUID都是不一致的,因此当作库-表合并时,不会出现主键冲突,这是自增主键作不到的。
2)自增主键 的长度相对较小,并且自增主键只能是数字,因此索引更快,磁盘空间更小,在数据插入时虽然会致使节点的分裂可是不会移动。
使用 insert t values(),() 比使用批处理使用 insert t values();insert t values(); 要快上好几倍,因此创建使用第一种方式,固然若是你可使用 insert t select ,那是最好不过了。在使用第一种方式也有注意的地方,若是values 里面已经有主键的值了,那么使用并发操做会发生锁超时,缘由应该是在数据惟一性检查那里作了同步,若是没有主键的值,那么并发是最快的,由于它采用互斥增加方式生成主键ID。
《mysql 技术内幕》