MySql中GUID与Int自增主键

建以下数据表: 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会得到最佳的性能。

猜你喜欢

转载自hudeyong926.iteye.com/blog/2424043
今日推荐