数据库主键目前主要有两种:
a、自增数值型
优:占用空间小,插入快,有序对索引友好,易懂
缺:多数据库迁移会有重复键值问题,有可能爆表
b、GUID
优:多数据库唯一
缺:占用空间大,无序对索引不友好,不易懂
察看GUD发现最主要的问题还是在于无序对索引不友好,会引起性能问题,已知有以下两种方式可以解决:
1、基于Twitter的snowflake算法,生成一个long型ID,参考代码如下:
public class IdWorker
{
private long workerId;
private long datacenterId;
private long sequence = 0L; private static long twepoch = 1288834974657L; private static long workerIdBits = 5L;
private static long datacenterIdBits = 5L;
private static long maxWorkerId = -1L ^ (-1L << (int)workerIdBits);
private static long maxDatacenterId = -1L ^ (-1L << (int)datacenterIdBits);
private static long sequenceBits = 12L; private long workerIdShift = sequenceBits;
private long datacenterIdShift = sequenceBits + workerIdBits;
private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private long sequenceMask = -1L ^ (-1L << (int)sequenceBits); private long lastTimestamp = -1L;
private static object syncRoot = new object(); public IdWorker(long workerId, long datacenterId)
{ // sanity check for workerId
if (workerId > maxWorkerId || workerId < )
{
throw new ArgumentException(string.Format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < )
{
throw new ArgumentException(string.Format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
} public long nextId()
{
lock (syncRoot)
{
long timestamp = timeGen(); if (timestamp < lastTimestamp)
{
throw new ApplicationException(string.Format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
} if (lastTimestamp == timestamp)
{
sequence = (sequence + ) & sequenceMask;
if (sequence == )
{
timestamp = tilNextMillis(lastTimestamp);
}
}
else
{
sequence = 0L;
} lastTimestamp = timestamp; return ((timestamp - twepoch) << (int)timestampLeftShift) | (datacenterId << (int)datacenterIdShift) | (workerId << (int)workerIdShift) | sequence;
}
} protected long tilNextMillis(long lastTimestamp)
{
long timestamp = timeGen();
while (timestamp <= lastTimestamp)
{
timestamp = timeGen();
}
return timestamp;
} protected long timeGen()
{
return (long)(DateTime.UtcNow - new DateTime(, , , , , , DateTimeKind.Utc)).TotalMilliseconds;
}
}
2、用NewId开源项目
项目地址:https://github.com/phatboyg/NewId
使用方法:
NewId id = NewId.Next(); //produces an id like {11790000-cf25-b808-dc58-08d367322210} // Supports operations similar to GUID
NewId id = NewId.Next().ToString("D").ToUpperInvariant();
// Produces 11790000-CF25-B808-2365-08D36732603A // Start from an id
NewId id = new NewId("11790000-cf25-b808-dc58-08d367322210"); // Start with a byte-array
var bytes = new byte[] { , , , , , , , , , , , , , , , };
NewId theId = new NewId(bytes);