|
|
1
92
当我询问如何为对象存储guid的最佳方法时,我的DBA问我为什么需要存储16个字节,而我可以用一个整数在4个字节中执行相同的操作。既然他向我提出了那个挑战,我想现在是时候提出来了。有人说… 如果要最大限度地利用存储空间,可以将guid存储为char(16)二进制文件。 |
|
|
2
39
我会把它储存成一个字符(36)。 |
|
|
3
30
除了Thabaddawg给出的答案之外,还可以使用这些方便的函数(这要归功于我的一个更明智的库),从36长度的字符串返回到16字节数组。
为了更好地遵循代码,以下面的按数字排序的guid为例。(非法字符用于说明目的-每个地方都有一个唯一的字符。)函数将转换字节顺序,以获得更优的索引聚类的位顺序。重新排序的GUID显示在下面的示例中。
破折号:
|
|
|
4
24
char(36)是个不错的选择。也可以使用mysql的uuid()函数返回36个字符的文本格式(带连字符的十六进制),该格式可用于从数据库中检索此类ID。 |
|
|
5
16
“更好”取决于你在优化什么。 您对存储大小/性能和易开发性有多关心?更重要的是-您是否生成了足够多的guid,或者足够频繁地获取它们,这很重要?
如果答案是“否”,
|
|
|
6
8
二进制(16)会很好,优于varchar(32)。 |
|
7
6
应该调整KCD发布的guidToBinary例程,以考虑guid字符串中时间戳的位布局。如果字符串表示一个版本1的uuid,就像uuid()mysql例程返回的那样,那么时间组件将嵌入字母1-g中,不包括d。
当您转换为二进制时,索引的最佳顺序是:efg9abc12345678d+其余。 您不想将12345678换成78563412,因为big endian已经生成了最佳的二进制索引字节顺序。但是,您确实希望将最重要的字节移到较低的字节前面。因此,EFG先进入,然后是中间位和较低位。在一分钟内用uuid()生成一打左右的uuid,您应该看到这个顺序如何产生正确的排名。
前两个UUID的生成时间最接近。它们只在第一个块的最后3个字节中变化。这些是时间戳的最低有效位,这意味着当我们将其转换为可索引字节数组时,我们希望将它们向右推。作为一个反例,最后一个ID是最新的,但是KCD的交换算法会把它放在第三个ID之前(3e在DC之前,最后一个来自第一个块的字节)。 索引的正确顺序是:
有关支持信息,请参阅本文: http://mysql.rjweb.org/doc.php/uuid ***请注意,我不会从时间戳的高12位中拆分版本nibble。这是你的例子中的d字节。我只是把它扔在前面。所以我的二进制序列最终被定义为9abc等等。这意味着我所有的索引UUID都以相同的一个字节开始。这篇文章也做了同样的事情。 |
|
|
9
1
我建议使用下面的函数,因为@bigh_29所提到的函数将我的guid转换为新的guid(因为我不理解的原因)。而且,在我在桌子上做的测试中,这些测试速度有点快。 https://gist.github.com/damienb/159151
|
|
|
10
-4
如果您有一个char/varchar值格式化为标准的guid,那么您可以使用简单的cast(mystring作为binary16)将其存储为binary(16),而不必使用concat+substr的令人难以置信的序列。 二进制(16)字段的比较/排序/索引速度比字符串快得多,而且在数据库中占用的空间也少了两倍。 |