java UUID作为主键:它的非连续性的缺点

gkl3eglg  于 2023-04-28  发布在  Java
关注(0)|答案(2)|浏览(122)

对于新的MySQL数据库,我们考虑使用UUID作为主键,存储为BINARY(16)。键值将由Java应用程序中的下面的函数生成,或者由数据加载中的UUID_TO_BIN(UUID())内置函数生成。

UUID.randomUUID();

public static byte[] convertUUIDToBytes(UUID uuid) {
    ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
    bb.putLong(uuid.getMostSignificantBits());
    bb.putLong(uuid.getLeastSignificantBits());
    return bb.array();
}

public static UUID convertBytesToUUID(byte[] bytes) {
    ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
    long high = byteBuffer.getLong();
    long low = byteBuffer.getLong();
    return new UUID(high, low);
}

Oracle中的SYS_GUID()生成完全随机的数字,通常用作一级主键或唯一键,但许多博客声称使用 UUID Ver 4 会有严重的性能问题,因为它的非顺序性质Blog on MySQL site
1.使用 UUID Ver 4 检索数据时是否存在性能问题。我们的数据在插入顺序方面是完全随机的,我们的查询访问第一个插入行的机会与最近插入行的机会相同。我们不希望查询结果中的行按插入顺序显示。我们也不需要查询以主键值作为范围的行。
1.插入行时是否会出现任何性能问题。
我们确实知道,与UUID作为键相比,数字将具有更好的性能,但UUID是我们数据的重要组成部分,大多数查询将使用UUID作为键。

wqsoz72f

wqsoz72f1#

使用UUID时存在性能差异和存储大小差异。这些差异是否大到足以使它成为应用程序的交易破坏者,这是您必须自己测试的事情。
Percona在这个主题上做了一些很棒的博客。
02 The Dog(2007)
对于auto_increment键,加载过程花费了1小时50分钟,加载速度为40305行/秒。对于UUID过程花了超过12个小时,并仍在继续。从MySQL的状态,我可以看到它是加载约200行/秒,它仍然是放慢了一点,作为关键文件的增长。所以在这个小例子中,我们有大约200倍的性能差异,这是值得考虑的
02 The Dog(2015)
...下图向我们展示了UUID()会导致严重的碎片,因为它会导致页面在整个表中被分割。这被认为是“昂贵的”,因为ibd文件现在比UUID()优化方法大2倍以上,比使用AUTO_INCREMENT的主键大3倍左右。

  • 02 The Dog(2014)

水平轴-刀片数量x 25,000
纵轴-所用时间(秒)

我会避免使用UUID作为主键 *,除非 * 您在多个MySQL示例中存储数据(即。e.分片),并且您需要确保它们在所有示例中保持唯一。

yiytaume

yiytaume2#

不要用V6。
MySQL 8的UUID_TO_BIN()做了V6所做的事情,但是在从十六进制转换为二进制时做了这件事。也就是说,如果在使用BINARY(16)函数后存储在该函数中,则不需要V6来获取引用的局部性。
类似地,MariaDB 10.7为UUID添加了一个成熟的“数据类型”。它显示V1,但将位混洗为一个16字节的类似二进制的数据类型。
我的讨论,从十多年前:http://mysql.rjweb.org/doc.php/uuid
(感谢V6的链接;我会把它加到我的博客里。)

相关问题