如何将uuid作为数字存储?


76

根据问题的答案,即MySQL中的UUID性能,回答者建议将UUID存储为数字而不是字符串。我不太确定该怎么做。有人可以建议我吗?我的ruby代码如何处理呢?


5
仅当您使用UUID主键时才会出现性能问题,因为UUID并不是非常有效的主键。为什么需要UUID?您能保留UUID并仅使用自动增量作为主键吗?
汤姆·史密斯

4
@ThomSmith关于“ UUID不是非常有效的主键” ..希望引用一个解释原因的资料来源?
Pacerier

2
这是一条更大的数据,通常需要更多指令进行比较。它不是顺序的,因此索引的开销仅高一点。而且,当然,如果您将其存储为字符串而不是128位数字(如OP那样),情况将会恶化。这不是一个可怕的密钥,但是除非有一些外部原因,否则我不会使用它。
汤姆·史密斯

自动增量会导致多个共享数据库服务器出现问题-通常会导致键冲突。UUID旨在解决类似问题。如果您不是将UUID存储为文本,而是将其存储为bin(16),那么您当然会有一个数字UUID。比较二进制比文本要快。这是一个讨论此问题的站点-mysql.rjweb.org/doc.php/uuid
Jeff Clayton

Answers:


108

如果我理解正确,那么您在主列中使用的是UUID吗?人们会说,常规(整数)主键会更快,但是还有另一种使用MySQL暗面的方法。实际上,当需要索引时,MySQL使用二进制文件的速度比其他任何东西都要快。

由于UUID为128位,并以十六进制形式编写,因此可以非常轻松地加速和存储UUID。

首先,在您的编程语言中删除破折号

110E8400-E29B-11D4-A716-446655440000110E8400E29B11D4A716446655440000

现在它是32个字符(就像MD5哈希,它也可以使用)。

由于BINARYMySQL中的单个文件的大小为8位,BINARY(16)因此UUID的大小为(8 * 16 = 128)。

您可以使用以下命令插入:

INSERT INTO Table (FieldBin) VALUES (UNHEX("110E8400E29B11D4A716446655440000"))

并使用以下查询:

SELECT HEX(FieldBin) AS FieldBin FROM Table

现在,以您的编程语言,在9、14、19和24位置重新插入破折号以匹配您的原始UUID。如果位置总是不同,则可以将该信息存储在第二个字段中。

完整示例:

CREATE TABLE  `test_table` (
    `field_binary` BINARY( 16 ) NULL ,
    PRIMARY KEY (  `field_binary` )
) ENGINE = INNODB ;

INSERT INTO  `test_table` (
    `field_binary`
)
VALUES (
    UNHEX(  '110E8400E29B11D4A716446655440000' )
);

SELECT HEX(field_binary) AS field_binary FROM `test_table`

如果要对任何十六进制字符串使用此技术,请始终length / 2对字段长度进行操作。因此,对于sha512,该字段将是BINARY (64)因为sha512编码的长度为128个字符。


3
@Chamnap假设您的数据库中有1万行,并且已经使用UNHEX函数添加了它们,并且您要搜索UUID 110E8400-E29B-11D4-A716-446655440000。就像这样:SELECT * FROM test_table WHERE field_binary LIKE CONCAT("%", UNHEX('110E8400E29B11D4A716446655440000'), "%")
DavidBélanger2012年

5
如果有时间可以阅读。注重3点:xaprb.com/blog/2009/02/12/...
大卫·贝朗格

4
@Chamnap是的,你应该做。我只是想演示一下,是否要在LIKE中使用带有UNHEX函数的角色%。你可以做的WHERE Field = UNHEX('110E8400E29B11D4A716446655440000')。除了WHERE Field = 3使用十六进制字符串(搜索,插入,在何处,更新,删除等)外,您还可以使用UNHEX来封装字段,而要从MySQL中读取时,可以使用HEX来封装字段(选择)。
DavidBélanger2012年

2
@DavidBélanger您说过,与int相比,MySQL索引二进制文件的速度更快。有资料吗?
Pacerier

4
在BINARY类型上的措辞令人困惑。mysql中的单个“ BINARY”大小为8位,这就是BINARY(16)起作用的原因(8 * 16 = 128,即UUID的大小)。它不是“店在1位十六进制什么做的4位”。这不可能。“每个BINARY类型的单位大小中都可以存储两个十六进制值,它本身是8位大小,因此我们需要16个单位大小的BINARY,因此我们将使用BINARY(16)。”
lilbyrdie14年


0

我认为使用二进制不是一个好主意。

假设您要查询一些值:

SELECT HEX(field_binary) AS field_binary FROM `test_table`

如果我们返回几个值,那么我们将多次调用HEX函数。

但是,主要问题是下一个:

SELECT * FROM `test_table`
    where field_binary=UNHEX('110E8400E29B11D4A716446655440000')

并在where中使用函数,只需忽略索引。

SELECT * FROM `test_table`
    where field_binary=x'skdsdfk5rtirfdcv@#*#(&#@$9' 

可能导致很多问题。


1
您是否测试过关注的表现?您建议HEX和UNHEX的性能比使用36个字符的字段作为索引的性能问题要差。我什至不必测试,知道那是错误的。(但是,由于您认为否则,请进行测试)其次,显示的代码并不是如何最好地处理它。您的所有数据库代码都应仅涉及16字节字段。不要十六进制和十六进制。只需将其作为那16个字节传递给您的数据库即可。直接使用这些16字节的值进行所有查询。仅在显示给user时,才需要将其转换为用户友好的版本。
ToolmakerSteve
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.