我想做些类似imgur和其他大多数网站的事情:我想在URL中使用随机字符串来标识用户正在寻找的帖子。
使用像这样的随机字符串作为主键可能不是一个好主意,并且在用户发送提交时确保随机生成的字符串尚未被使用会随着时间的流逝而减慢表的速度。 ,因为它将需要检查越来越多的记录以确保没有重复项。如何实现像这样的随机字符串以进行识别?
我的想法是,请告诉我这是否真的是一个坏主意,那就是要有一个包含这些随机字符串的表。该表将如下所示:
| submissionId | stringId
+--------------+----------
| 1 | rbMZV
+--------------+----------
| 2 | MQyPi
+--------------+----------
| NULL | hfXL7
生成这些字符串时,它们没有分配submissionId,例如我的示例表中的“ hfXL7”。当用户提交提交时,我的脚本将采用第一个随机生成的字符串,该字符串尚未分配submittionId,并将在提交该提交时生成的submittionId添加到该记录。我在某个地方有一个过程,该过程会定期生成更多字符串,当人们进行更多提交时可以使用这些字符串,因此当有人进行提交时,总是至少会有一个随机生成的字符串,而没有submittionId。
答案 0 :(得分:3)
这是三种基本方法:
每种都有优点和缺点:
上述方法(3)的演示
如何在MySQL中实现即时生成器的在线演示:http://rextester.com/TKGPZ41053
排列数计算
如果区分大小写字母数字,则总共有62个不同的字符。因此,每种长度的可能排列数目如下:
Characters | Permutations
1 | 62
2 | 3844
3 | 238328
4 | 14776336
5 | 916132832
6 | 56800235584
7 | 3521614606208
8 | 218340105584896
9 | 13537086546263552
10 | 839299365868340224
答案 1 :(得分:1)
就像汉斯·帕森特(Hans Passant)在评论中说的那样,一种简单的策略是对URL中自动递增的主键进行base64编码。
此方法的一个更安全的变体是使用分组密码对您的主键值进行加密,然后对结果进行base64编码(在URL中)。这具有固定长度值的优点。
我已在项目中成功使用Skip32(Skipjack算法的一种变体)。
答案 2 :(得分:0)
这实际上取决于首先不使用PK的目的以及这些合成版本需要使用多长时间。
尽管您仍在进行生成和检查唯一值的工作,但您提出的建议是可以的。除了找到未使用的代码外,我可能会提前生成submissionId
和代码。两个并发的数据库访问都将找到相同的“未使用”行(或相互阻塞,这取决于您如何实现)。都不是很好,也不是必需。
您还可以对行中的PK或PK +其他[不可变]元素进行加密。在网络世界中,您可能会使用会话获取临时代码,并且可能使用每个用户唯一的代码。这真的取决于目的。
答案 3 :(得分:0)
我会尝试一些稍有不同的事情,并避免在所有随机物品填满之前填写表格。我将有一个包含以下列的表格:
CREATE TABLE [dbo].[Links]
(
[Id] [bigint] IDENTITY(1,1) NOT NULL
, [StringId] [nvarchar](5) NOT NULL
, [OtherInfo] [<whatever type you need]
, CONSTRAINT [PK_LinksId] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
)
Id
列作为群集主键将有助于维持插入率。
然后,我将在StringId
列上添加唯一索引以进行快速查找。由于您不会寻找部分StringId
而是寻找完整的CREATE UNIQUE NONCLUSTERED INDEX [IDX_StringId] ON [dbo].[Links]
(
[StringId]
)
,因此索引应该提供必要的速度。
Auto Update Statistics Asynchronously
如果以某种方式两次生成相同的stringId,SQL将捕获它,您将能够生成另一个随机字符串。
为避免任何意外的变慢,我还考虑将true
设置为IDX_StringId
,以便在统计信息过时并需要更新时不会阻止查询。
最后,需要计划维护,以确保{{1}}索引不会变得过于分散。 Microsoft在下面的address中提供了一个存储过程,该存储过程可以每晚运行。
答案 4 :(得分:0)
我质疑你的主张
并确保在用户发送提交内容时尚未使用随机生成的字符串,这会随着时间的推移降低表的速度
SQL索引(唯一索引或其他索引)通常存储在B-Trees中,因此它会变慢,但是直到您超出可以完全加载到服务器RAM中的索引记录的数量时,这种情况才会明显(这会超过uint32.max
条记录)。此时,您可以升级服务器或仅实施sharding策略。
在您想像的规模上,并发(例如部分提到的@LoztInSpace)将是要解决的难题。但是,对于几乎我能想到的任何流量级别,仍然可以使用乐观的插入以及适当的分片级别
答案 5 :(得分:0)
您需要随机生成的通用/全局唯一标识符,并且大多数数据库为此提供了内置函数。newid()和newsequentialid()是T-SQL提供的两个函数,可用于唯一标识您的行。
INSERT cust (CustomerID, Company, Fax) VALUES (NEWID(), 'Wartian Herkku','981-443655');
如果您决定使用它,我建议使用newsequentialid()而不是newid(),原因为performance benefit of seq id