一尘不染

MySQL主键:UUID / GUID与BIGINT(时间戳+随机)

sql

tl; dr:如果我不想处理UUID,将{unixtimestamp}
{randomdigits}(例如1308022796123456)的行ID分配为BIGINT是一个好主意吗?

只是想知道是否有人对分配给跨多台服务器的数据库记录的ID / PRIMARY KEY的性能或其他技术考虑/限制有所了解。

我的PHP + MySQL应用程序在多台服务器上运行,并且数据需要能够合并。因此,我已经不再使用识别行的标准顺序/ auto_increment整数方法。

我对解决方案的研究使我想到了使用UUID /
GUID的概念。但是,需要修改我的代码来处理将UUID字符串转换为MySQL中的二进制值的需求似乎有些麻烦/工作。由于存储和性能方面的原因,我不想将UUID存储为VARCHAR。

存储在二进制列中的UUID的另一个可能的烦人之处是,当在PhpMyAdmin中查看数据时,行ID并不明显-虽然我可能是错的-
但是总的来说,直数似乎更简单,并且在任何情况下都是通用的一种无需转换的数据库系统。

作为中间立场,我想到了将我的ID列设置为BIGINT的想法,并使用当前的unix时间戳和6个随机数字来分配ID。假设我的随机数大约为123456,今天生成的ID为:
1308022796123456

对于在同一秒内创建的行,每千万分之一的发生冲突的可能性对我来说很好。我没有快速进行大量行创建。

我读到的关于随机生成的UUID的一个问题是,它们不利于索引,因为值不是连续的(它们分布在各处)。MySQL中的UUID()函数通过根据当前时间戳生成UUID的第一部分来解决此问题。因此,我复制了在BIGINT开始时使用unix时间戳的想法。我的索引会变慢吗?

我的BIGINT想法的优点:

  • 给我UUID的多服务器/合并优势
  • 几乎不需要更改我的应用程序代码(所有内容都已编程为处理ID的整数)
  • UUID的一半存储(8字节vs 16字节)

缺点:

  • ??? -如果您能想到的话,请告诉我。

一些后续问题可以解决:

  1. 最后我应该使用少于或少于6个随机数字吗?它会对索引性能产生影响吗?

  2. 这些方法之一是否是“ randomer” ?:使PHP生成6位数字并将它们连接在一起-VS-使PHP生成1-999999范围内的数字,然后进行零填充以确保6位数字。

感谢您的提示。对不起,那堵墙。


阅读 677

收藏
2021-03-17

共1个答案

一尘不染

我在职业生涯中遇到了这个问题。我们使用时间戳+随机数,并在我们的应用程序扩展时遇到了严重的问题(更多的客户端,更多的服务器,更多的请求)。当然,我们(愚蠢地)只使用了4位数字,然后更改为6位数字,但是您会惊讶地发现错误仍然经常发生。

在足够长的时间内,可以 确保
您得到重复的密钥错误。我们的应用程序是关键任务,因此即使由于固有的随机行为而导致失败的最小机会也是不可接受的。我们开始使用UUID来避免此问题,并仔细管理了它们的创建。

使用UUID,索引的大小将增加,索引的增加将导致性能下降(也许不明显,但仍然较差)。但是MySQL支持本机UUID类型(切勿使用varchar作为主键!!),甚至比bigint都可以高效地处理索引,搜索等。索引的最大性能损失几乎总是被索引的行数,而不是被索引的项目的大小(除非您要在长文本或类似的东西上进行索引)。

回答您的问题:如果您不打算大幅度扩展应用程序/服务,Bigint(带有随机数)将是可以的。如果您的代码可以在不做太多更改的情况下处理更改,并且如果发生重复的键错误,则应用程序也不会爆炸,请继续使用。否则,咬住子弹,然后选择更重要的选择。

您以后总是可以实施更大的更改,例如切换到完全不同的后端(我们现在面对的是…:P)

2021-03-17