2011-07-08 14 views
6

RFC 4122のセクション4.4(http://www.ietf.org/rfc/rfc4122.txt)に記載されているように、v4 UUIDを生成するMySQLストアド関数を記述しようとしています。いくつかの調整後の私の最初の素朴な取り組みは以下の通りである:上記の機能は非常に遅いですMySQL UUID v4ストアドファンクションを高速化するにはどうすればよいですか?

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 

:ビルトインUUID()よりもほぼ100倍遅く、MySQLのBENCHMARK()の特徴に応じました。 MySQLのC APIを使ってUDFを書くのに手間がかかっていますが、ここで実行時間から何桁も削減することができますか?

既に存在する、よく評価されているUUID UDFまたはストアドプロシージャがある場合は、そのことについても喜んでお聞きしたいと思います。

+0

私は答えは分かりませんが、既に述べたMySQLのUUID()を使う代わりに、独自の関数を作りたいのですが(MySQLのものがRFC 4122と違うかどうかは分かりません。尋ねるために)? –

+0

MySQLの 'UUID()'はRFC4122に従ってuuidを生成せず、それを生成する方法によって文ベースの複製が中断されます。 –

+2

この関数は、ステートメントベースのレプリケーションも中断します。 binlog形式を "MIXED"または "ROW"に設定することで、ログの再生で関数が呼び出されることはなく、UUID()を実行可能にする実際の行の値を挿入することで回避できます。また、関数が重複するUUIDを生成しないことを保証するものはありますか?唯一のランダムな要因は、RAND()への5回の呼び出しです(最初は遅くなっています)。私はMySQLのUDFを書いて、関数を使ってソリューションを作成するのではなく、その方法で実装すると、パフォーマンスが向上します。 –

答えて

9

これは、正確性や性能についてはテストしませんでした。 2つではなく1つの連結のみを行うという考え方です。

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を使うのですか?

+0

re 'READS SQL DATA':私は現在ステートメントベースのレプリケーションを使用しなければなりませんし、' DETERMINISTIC'、 'NO SQL'、または' READS SQL DATA'はそれを中断しないために必要です。 –

+0

しかし、このステートメントは複製するのが安全ではないことは知っていますよね? – TehShrike