mysql - 考虑性能和友好 URL 时要实现的数据库密钥设计
问题描述
介绍
所以我最近问了一个关于信息安全堆栈交换的问题,这让我决定我不想在外部公开自动递增的整数 ID ,不是因为安全原因,而是因为我认为这会让用户非常不安得出有多少学生在他们之前报名的结论。
问题
但这导致我做出另一个决定,如果我要使用 GUID 或其他某种随机生成的字符串 id,我是否应该将其用作主键?由于我选择的 RDBMS 是 MySQL,而选择的数据库引擎是 InnoDB,因此在 InnoDB 中,主键始终是 clustered,而所有其他索引都是 non-clustered。如果我将 GUID 设为主键,那么插入次数越多,性能就越差。
建议的解决方案
因此,我正在考虑为所有表保留自动递增的整数 id,以及将我的所有外键保留为整数 id,但还要为每个表添加一个唯一索引以存储 GUID,这将在外部公开. 然后每次我在我的 API 中收到请求,并且我想将Student
表与Books
数据库中的表连接起来时,我需要做的第一件事就是查询数据库以确定指定学生 GUID 的整数 id 是什么.
由于我认为我绝对不是第一个遇到这个问题的人,或者类似的问题,这是解决我的问题的最佳方法吗?
解决方案
是的,这是合理的。
将 GUID 作为二级索引,INT AUTO_INCREMENT
将低效部分限制为该索引。建议您打包 GUID——而不是CHAR(36) CHARSET ascii
(始终为 36 个字节),将其打包成BINARY(16)
(始终为 16 个字节)。再加上 4-byte INT
,一百万学生可能需要 50MB。与您的多 GB 磁盘相比很小?
为了最小化开销,只需将 GUID 设置为Students
表上的辅助键。这主要消除了“我需要做的第一件事是查询数据库......”的额外步骤。
备择方案:
- 一个随机数。更小,但需要避免重复。
- 的加盐和散列函数
AUTO_INC
。
推荐阅读
- node.js - JSON Parse 错误:尝试更改值时发生意外的 EOF
- reactjs - 加载包含 jwt-token 的html
- android - 在 Intent 中设置类型以启动 Activity
- android - 仅编辑edittext android中的特定内容
- redirect - 如何让谷歌搜索显示新域而不是旧域?
- django - 即使所有设置都很好,Django也无法加载静态文件
- java - 需要使用任何java API从给定的数字列表中随机生成每个值相同次数的数字
- java - 使用java的条形图
- laravel - Turbolink 在 Livewire 版本 2 中不工作
- java - 当我执行 mvn package 时,spring-boot-configuration-processor.jar 不会被打包。