以最少的资源使用检查数据库的唯一随机值


Check unique random value against database with minimal resource use

这更像是一个最佳实践问题。我正在使用以下参数生成一个随机字符串标识符:

  • 长度:7 个字符
  • 种子:A-Za-z0-9(小写+大写字母和数字)

在插入之前,我需要检查数据库中是否存在该字符串。我可以通过两种方式做到这一点:

  1. 运行do...while循环。在其中,生成一个随机字符串,每次使用 COUNT(*) 直到 count === 0 查询数据库。
  2. 首先使用单个查询从数据库中获取所有现有的唯一字符串,然后运行 do...while 循环以生成不在提取数组中的随机字符串。
对我来说很明显,

第二种方法在技术上对数据库服务器的资源密集度较低,因为只有一个查询,而不是一遍又一遍地查询。所以我倾向于这种方法,但我看到了两个潜在的警告:

大型数据库,以及从获取和插入之间经过的时间。

  • 大型数据库结果:在我需要考虑切换到第一种方法之前,查询结果中可以有多少行?换句话说,数据库服务器上大型结果集的压力何时低于运行多个后续查询?1,000 个结果?5,000?20,000?

  • 获取和插入之间的时间:如果我使用第二种方法,当两个或多个用户尝试同时运行同一函数时,我会看到风险。第一个用户的结果集(从数据库中获取的唯一字符串)可能不包括在查询后 2 毫秒刚刚添加的其他用户的唯一字符串。这可能会在数据库中产生重复项。

第二种方法在生产中是否真的可行,还是只是一个梦想?

第二个选项对我来说似乎不切实际。如果表中只有几行,则冲突风险较低,如果有很多行,则冲突的风险会增加,但在 php 端获取所有行的内存效率不高。

第一个解决方案对我来说似乎更好。

但我认为可以使用第三种选择。在 MySQL 中的随机值上添加一个唯一索引。生成一个随机值,然后尝试插入它。如果发生冲突,请捕获错误。这是有效的,因为MySQL可以快速检查值在索引时是否存在。此方法没有并发问题。

唯一需要注意的是(对于所有方法)是,当表中的行数很高时,您将很难找到尚未使用的值。要降低冲突风险,可以增加随机值的大小。您还可以创建另一个包含未使用值的表,并在该表的值太少时用其他算法填充该表。