我正在管理一个用于付款处理系统的MySQL数据库。由于各种遗留原因,它最初是使用CHAR(14)构造的,用于许多主键,这些主键基于识别数据类型的前缀存储顺序ID,后跟表示顺序大数目的base36编码字符串,例如>
“ PA00003NFMWHMQ”翻译为“付款286103946050”
这里的优点是半唯一键仍然是顺序键,缺点是用于聚集索引和非聚集索引的值较大,会减慢联接和查找的速度,并需要额外的内存/存储空间。
尽管我也喜欢唯一性,但我正在考虑在发布API之前将它们全部迁移为整数。我也提防过早的优化。
我不是在这里寻找明确的答案,只是一些有经验的意见。
谢谢!
答案 0 :(得分:1)
我的第一个想法是“您是否仍然必须挂起此ID才能向后兼容?”像您一样具有含义的ID倾向于在外部系统中存储和引用。您是否将获得一个表,该表具有供内部使用的整数主键,一个char(14)
旧式ID和两个索引?那可能仍然是一种改进,但是会影响这种改变是否值得。在我的其余评论中请记住这一点。
如果您可以完全切换为自动递增的整数并摆脱特殊的ID生成代码,那肯定会使事情变得更简单并且插入速度更快。您需要确定多少简单快捷。仅仅是创建代码中某个地方的一个额外功能,它不会困扰任何人?还是会影响整个地方的代码和设计?
...缺点是用于聚集索引和非聚集索引的值较大,会减慢联接和查找的速度,并需要额外的内存/存储空间。
与任何性能要求一样,第一件事就是调查它们是否正确。 char(14)
键真的会减慢连接速度并消耗内存和存储吗?
char(14)
(14个字节)不大于整数(4个字节)。每行额外的10个字节每百万条记录仅10 MB。但这仅仅是存储密钥。每个引用又增加了10个字节。每个包含它的索引又增加了10多个字节。不过,如果不进行衡量,我不会认为这是一个主要的存储和内存问题。
磁盘和内存通常比开发人员时间便宜得多。这并不意味着浪费,而是考虑节省几场演出是否值得,尽管这可能需要花费很长时间(以及测试)。或者,如果您可以购买更大的磁盘和更多的内存。例如,我有一个项目可以从使用枚举字段而不是字符串中受益。但是我没有打扰,因为那将意味着开发人员有更多时间进行更改并维护枚举字段。相反,购买额外的磁盘仍然便宜。这可能会改变,到时我会重新考虑。
类似于联接。如果将它们编入索引,则无论是char
还是int
,它们都应该表现良好。但是您需要测试。
我建议您制作一个经过清理的数据库副本,或者使用测试工厂生成一个合适的大小,并使用char(14)
和int
运行一些性能测试。请务必测试现实情况,以及此更改是否会对性能产生实际影响。仅运行裸SQL查询可能会给您带来对其性能影响的巨大印象。也调用您在生产环境中使用的实际函数,它们可能会淹没任何SQL影响。
“ PA00003NFMWHMQ”翻译为“付款286103946050”
我正在考虑在发布API之前将它们全部迁移为整数
将主键(或任何其他实现信息)暴露于外界具有安全性和兼容性考虑。攻击者可以使用其知识,例如,他们可以预测下一个密钥是什么。不要这样做。
相反,分配要公开的每个事物的对象,例如UUIDv4(不要使用MySQL的UUID函数,这是可猜测的UUIDv1),例如Store them as binary(16)
。 {{3}}(如果空间是一个大问题)。
然后,您的主键是什么都没有关系。您可以根据需要更改设计。
这里的优势是半唯一键仍然是顺序的...
这是一个难题。主键必须是唯一的,所以我不确定“半唯一”的含义。你是说跨表吗? A列中的行的ID与B列中的行可能是唯一的吗?如果是这种情况,请考虑UUID主键。或者考虑一下 semi 部分,这是否真的是您可以实际使用的优势。