如何加速我的MySQL UUID v4存储函数?

6

我正在尝试编写一个MySQL存储函数来生成RFC 4122第4.4节中描述的v4 UUID(http://www.ietf.org/rfc/rfc4122.txt)。经过一些调整后,我的初始努力如下:

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或存储过程,我也很乐意听听。


我不知道答案,但是你为什么要创建自己的函数,而不是使用已经提到的MySQL的UUID()函数呢?(我不知道MySQL的函数是否与RFC 4122有所不同,如果有的话,对不起问一下) - Michael J.V.
MySQL的UUID()并不按照RFC4122生成UUID,而它生成的方式会破坏基于语句的复制。 - Richard Simões
2
你的函数还会破坏基于语句的复制。为了避免这种情况,可以将binlog格式设置为“MIXED”或“ROW”,这样重放日志时不会调用函数,而是插入实际的行值,从而使UUID()可用。此外,如何保证您的函数不会生成重复的UUID?唯一的随机因素是对RAND()的5次调用(这也是其首次缓慢的原因)。我建议编写一个MySQL的UDF并通过该方式实现,而不是创建一个函数来实现解决方案,这应该能够获得更好的性能。 - Michael J.V.
为什么要首选使用UUID?也许基于CRC32的解决方案就足够了? - Dor
Michael J.V.:如果您将您的评论作为答案添加,我会接受它。我认为完全避免使用UDF将阻止我获得我所寻求的速度提升。 - Richard Simões
1个回答

8

我没有测试这个代码的正确性或性能。这只是一种将两个拼接操作合并为一个的想法。

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
;

此外,你为什么在你的函数中使用 READS SQL DATA?

关于READS SQL DATA:我目前必须使用基于语句的复制,而DETERMINISTICNO SQLREADS SQL DATA是必要的,以避免破坏它。 - Richard Simões
1
但是你知道这个语句不安全,不能直接复制吧? - TehShrike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接