依赖数据库的功能,mysql、sqlserver有主键自增功能,oracle、db2则没有;postgresql可以将序列值设置成默认值,实现主键自增功能。
没有跨平台需求时,可以考虑使用。分库、分表时,不能使用。
依赖数据库的功能,mysql没有序列。
没有跨平台需求时,可以考虑使用。分表可以使用,分库不能使用。
不依赖数据库。通过程序产生一个32位的不重复的字符串。由于字符串过长且无序,作为主键容易影响数据库性能,一般不建议使用。
使用一个单独的数据库表来记录其它表的主键值,模仿数据库序列的功能。
缺点是ID值和数据量容易被猜测(主键自增和数据库序列都有这个问题)。
数据量不是特别大的情况下,ID值可以设置为int,占用空间少,性能较好。
通用性好,可以跨平台。分表可以使用,分库不能使用。
使用一个长整型作为主键ID。最高1位是符号位(一般不用),41位用于存放时间戳(共69年),10位作为机器(共2014台机器),12位作为序列号(共4096个ID)。
ID无法被猜测,且隐藏了系统中数据量的大小。
适合分库、分表场合,是分布式系统的首选。即使不分表分库也是一个很好的选择。特别是数据量敏感或者ID需保密的表。
UJCMS(9.0及之前版本)的主键使用Table策略,主键表为ujcms_seq
。
由于获取主键需要使用数据库锁,频繁获取主键性能较低,所以一次会获取多个主键。默认一次获取50
个主键。配置文件为WEB-INF/classes/application.yaml
(源码则为src/resources/application.yaml
),配置项为ujcms.sequence-cache-size: 50
。
对于个别表需要单独调整主键缓存大小的,可以设置主键表ujcms_seq
的cache_size_
字段。该字段为0
则使用上述程序中的默认大小,如指定大于0
的值,则以数据库的设定为准。
由于一次取出多个主键值,一旦程序重启,未使用的主键值将会浪费,导致数据库表里的ID值不连续。这是正常现象,不影响程序使用。
com.ujcms.cms.core.service.SeqService
/**
* 获取下一个序列值
*
* @param name 序列名称。一般为表名。
*/
public int getNextVal(final String name) {
...
}
/**
* 获取下一个长整型序列值
*
* @param name 序列名称。一般为表名。
*/
public long getNextLongVal(final String name) {
...
}
从UJCMS 9.5开始,改用雪花主键。原因如下:
com.ujcms.commons.db.identifier.SnowflakeSequence
/**
* 获取下一个 ID
*
* @return 下一个 ID
*/
public synchronized long nextId() {
...
}
常规的雪花主键只能使用69
年,这个时间有一点偏少;而每毫秒可以产生4096
个主键,每秒可以产生4,096,000
个主键,则太多。
UJCMS中,增加了使用年限为552
年(69*2*2*2
),减少了每毫秒可产生的主键数量为512
(4096/2/2/2
),每秒可以产生512,000
个主键,即每秒51.2
万个主键。足够大多数情况下的使用。