如何提高MySQL UUID v4存储函数的速度?

如何提高MySQL UUID v4存储函数的速度?,mysql,stored-procedures,uuid,Mysql,Stored Procedures,Uuid,我正试图编写一个MySQL存储函数来生成v4 UUID,如RFC4122的第4.4节()所述。经过几次调整后,我最初的天真努力如下: CREATE FUNCTION UUID_V4() RETURNS BINARY(16) READS SQL DATA BEGIN SET @uuid = CONCAT( LPAD( HEX( FLOOR( RAND() * 4294967296 ) ), 8, '0' ), LPAD( HEX( FLOOR( RAND()

我正试图编写一个MySQL存储函数来生成v4 UUID,如RFC4122的第4.4节()所述。经过几次调整后,我最初的天真努力如下:

CREATE FUNCTION UUID_V4()
RETURNS BINARY(16)
READS SQL DATA
BEGIN
    SET @uuid = CONCAT(
        LPAD( HEX( FLOOR( RAND() * 4294967296 ) ), 8, '0' ),
        LPAD( HEX( FLOOR( RAND() * 4294967296 ) ), 8, '0' ),
        LPAD( HEX( FLOOR( RAND() * 4294967296 ) ), 8, '0' ),
        LPAD( HEX( FLOOR( RAND() * 4294967296 ) ), 8, '0' )
    );
    SET @uuid = CONCAT(
        SUBSTR( @uuid FROM 1 FOR 12 ),
        '4',
        SUBSTR( @uuid FROM 14 FOR 3 ),
        SUBSTR( 'ab89' FROM FLOOR( 1 + RAND() * 4 ) FOR 1 ),
        SUBSTR( @uuid FROM 18 )
    );
    RETURN UNHEX(@uuid);
END
上面的函数非常慢:根据MySQL的
BENCHMARK()
特性,它比内置的
UUID()
慢近100倍。除了使用MySQL的C API编写UDF之外,我还能在这里做些什么改进,比如说,从其运行时中减少一个数量级


如果有一个已经存在的、广受好评的UUID UDF或存储过程,我也很高兴听到这个消息。

我没有测试它的正确性或性能。这只是一个想法,只做一个串联,而不是两个

create function uuid_v4()
returns binary(16)
begin
    set @h1 = lpad(hex(floor(rand() * 4294967296)), 8, '0');
    set @h2 = lpad(hex(floor(rand() * 4294967296)), 8, '0');
    set @h3 = lpad(hex(floor(rand() * 4294967296)), 8, '0');
    set @h4 = lpad(hex(floor(rand() * 4294967296)), 8, '0');

    set @uuid = concat(
        @h1,
        substr(@h2 from 1 for 4),
        '4',
        substr(@h2 from 6),
        substr('ab89' from floor(1 + rand() * 4) for 1 ),
        substr(@h3 from 2),
        @h4
    );
    return unhex(@uuid);
end
;

还有,为什么你要在函数中使用
读取SQL数据

我不知道答案,但是你为什么要创建自己的函数,而不是使用前面提到的MySQL的UUID()函数(我不知道MySQL的UUID()函数是否与RFC4122不同,所以如果很抱歉这么问的话)?MySQL的
UUID()
不会根据RFC4122生成uuid,它生成uuid的方式会中断基于语句的复制。您的函数也会中断基于语句的复制。您可以通过将binlog格式设置为“MIXED”或“ROW”来避免这种情况,这样日志的重放就不会调用函数,而是插入实际的行值,从而使UUID()可以使用。另外,有什么保证您的函数不会生成重复的UUID?您得到的唯一随机因素是对RAND()的5次调用(这是它首先变慢的原因)。我会为MySQL编写一个UDF,并以这种方式实现它,而不是通过函数创建解决方案,这样会产生更好的性能?也许基于CRC32的解决方案就足够了?Michael J.V:如果你能添加你的评论作为答案,我会接受的。我认为完全避免UDF会让我无法获得我想要的速度提升。re
读取SQL数据
:我目前不得不使用基于语句的复制,以及
确定性
无SQL
,或者
读取SQL数据
是不破坏SQL数据的必要条件。但您知道复制此语句是不安全的,对吗?