建以下数据表: int 主键自增表, guid主键表
CREATE TABLE `tbl_test_int` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `comment` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试int主键性能'; Insert into tbl_test_int(name,comment) values('TestMY', '哈哈,呵呵'); CREATE TABLE `tbl_test_measure` ( `guid` char(36) NOT NULL, `deviceID` int(50) DEFAULT NULL, `value` int(50) DEFAULT NULL, `value2` int(50) DEFAULT NULL, PRIMARY KEY (`guid`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='测试guid作唯一'; Insert into tbl_test_measure(guid,deviceID,value,value2) values (upper(replace(uuid(),'-','')), 1,2,3)
MySQL实现了 UUID,并且提供 UUID() 函数方便用户生成 UUID。在 MySQL 的 UUID() 函数中,前三组数字从时间戳中生成,第四组数字暂时保持时间戳的唯一性,第五组数字是一个 IEEE 802 节点标点值,保证空间唯一。使用 UUID() 函数,可以生成时间、空间上都独一无二的值。据说只要是使用了 UUID,都不可能看到两个重复的 UUID 值。当然,这个只是在理论情况下。如果是主从即M-S模式,最好是不使用mysql自带函数uuid来生成唯一主键。
如果真要使用uuid,可以在程序生成后,直接望DB里存储,这时主从的uuid就是一样的了
<?php /* * Twitter的SnowFlake算法 * 除了最高位bit标记为不可用以外,其余三组bit占位均可浮动,看具体的业务需求而定。 * 默认情况下41bit的时间戳可以支持该算法使用到2082年,10bit的工作机器id可以支持1023台机器,序列号支持1毫秒产生4095个自增序列id * * $particle = Particle::generateParticle($machineId);//生成ID * $timestamp = Particle::timeFromParticle($particle);//反向计算时间戳 */ abstract class Particle { const EPOCH = 1479533469598; const max12bit = 4095; const max41bit = 1099511627775; static $machineId = null; public static function machineId($mId = 0) { self::$machineId = $mId; } public static function generateParticle() { /* * Time - 42 bits */ $time = floor(microtime(true) * 1000); /* * Substract custom epoch from current time */ $time -= self::EPOCH; /* * Create a base and add time to it */ $base = decbin(self::max41bit + $time); /* * Configured machine id - 10 bits - up to 1024 machines */ if (!self::$machineId) { $machineid = self::$machineId; } else { $machineid = str_pad(decbin(self::$machineId), 10, "0", STR_PAD_LEFT); } /* * sequence number - 12 bits - up to 4096 random numbers per machine */ $random = str_pad(decbin(mt_rand(0, self::max12bit)), 12, "0", STR_PAD_LEFT); /* * Pack */ $base = $base . $machineid . $random; /* * Return unique time id no */ return bindec($base); } public static function timeFromParticle($particle) { /* * Return time */ return bindec(substr(decbin($particle), 0, 41)) - self::max41bit + self::EPOCH; } }
使用INT做主键的优点:
1、需要很小的数据存储空间,仅仅需要4 byte 。
2、查询操作时使用INT的性能比GUID好,所以使用int将会提高应用程序的性能。
3、index和Join 操作,int的性能最好。
4、容易记忆。
5、支持通过函数获取最新的值LAST_INSERT_ID()
使用INT做主键的缺点
1、如果经常有合并表的操作,就可能会出现主键重复的情况。
2、使用INT数据范围有限制。如果存在大量的数据,可能会超出INT的取值范围。
3、很难处理分布式存储的数据表。
使用GUID做主键的优点:
1、它是独一无二的。
2、出现重复的机会少。
3、适合大量数据中的插入和更新操作。
4、在分表时好处明显,跨服务器数据合并非常方便,数据可移植性强。
使用GUID做主键的缺点:
1、存储空间大(16 byte),因此它将会占用更多的磁盘大小。
2、很难记忆。join操作性能比int要低。
3、没有内置的函数获取最新产生的guid主键。
4、GUID做主键将会添加到表上的所以其他索引中,因此会降低性能。
总结:上面列出了GUID和INT两种数据类型做主键优缺点。我觉得,对于大数据量,建议使用guid做主键。而使用int会得到最佳的性能。