Как я могу ускорить мою хранимую функцию MySQL UUID v4? - PullRequest
6 голосов
/ 08 июля 2011

Я пытаюсь написать хранимую функцию MySQL для генерации UUID v4, как описано в разделе 4.4 RFC 4122 (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

Вышеуказанная функция довольно медленная: почти в 100 раз медленнее, чем встроенная UUID(), согласно функции MySQL BENCHMARK().Если не считать написания UDF с использованием MySQL C API, есть ли какие-либо улучшения, которые я могу сделать здесь, чтобы, скажем, сократить порядок на порядок по сравнению с его временем выполнения?

Если существует уже существующий, UDID UDID, рассматриваемый UUIDили хранимой процедуры, я был бы рад услышать об этом тоже.

1 Ответ

9 голосов
/ 22 июля 2011

Я не проверял это на правильность или на производительность.Это просто идея сделать одну единственную конкатенацию вместо двух.

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 в своей функции?

...