我正在尝试在MySQL中设计电子商务Web应用程序,但我在为用户表选择正确的主键时遇到问题。给出的示例只是一个示例示例。
用户表具有以下定义
CREATE TABLE IF NOT EXISTS `mydb`.`user` (
`id` INT NOT NULL ,
`username` VARCHAR(25) NOT NULL ,
`email` VARCHAR(25) NOT NULL ,
`external_customer_id` INT NOT NULL ,
`subscription_end_date` DATETIME NULL ,
`column_1` VARCHAR(45) NULL ,
`column_2` VARCHAR(45) NULL ,
`colum_3` VARCHAR(45) NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `username_UNIQUE` (`username` ASC) ,
UNIQUE INDEX `email_UNIQUE` (`email` ASC) ,
UNIQUE INDEX `customer_id_UNIQUE` (`external_customer_id` ASC) )
ENGINE = InnoDB
我面临主键候选列的以下问题:
Id列
赞成
缺点
电子邮件专栏
赞成
缺点
用户名栏
赞成
缺点
external_customer列
优点
可以作为客户的外部参考而不保留任何信息(也许可以使用不可编辑的用户名?)
缺点
可能会泄漏信息
为a选择用户表主键时的常见做法是什么 可扩展的电子商务Web应用程序?所有反馈意见
答案 0 :(得分:11)
我对你的一些分析没什么好说的。如果我削减了你的一些优点或缺点,那只意味着我不认为我有任何有用的东西可以添加。
Id列
赞成
- 没有商业意义(稳定的主键)
- 更快的表连接
- compacter index
首先,声明为NOT NULL UNIQUE的任何列或列集都具有主键的所有属性。您可以将它们中的任何一个用作外键引用的目标,这就是真正的所有内容。
在您的情况下,您的结构允许4列成为外键引用的目标:id,username,email和external_customer_id。您不必使用相同的所有时间。为90%的FK引用使用id可能是有意义的,并且10%的人可以发送电子邮件。
稳定性与列是否具有商业含义无关。稳定性与价值可能发生变化的频率和在何种情况下有关。 "稳定"并不意味着"不可变的"除非您正在运行Oracle。 (Oracle不能进行ON UPDATE CASCADE。)
根据您的表结构和索引,自然键可能会执行得更快。自然键使一些连接不必要。在构建生产数据库之前,我做过测试。我们可能需要几十年时间才能达到连接ID号码的能力将超过更少的连接和自然键。我已经在SO或DBA上写过这些测试。
您还有其他三个唯一索引。 ( Good 适合您。我认为至少有90%的人建立数据库都不能做到这一点。)因此,不仅仅是ID编号的索引比这三者中的任何一个都更紧凑;它还是附加索引。 (在此表中。)
电子邮件专栏
赞成
- 无
电子邮件地址可以被认为是稳定且独特的。您无法阻止人们共享电子邮件地址,无论其是否为外键引用的目标。
但电子邮件地址可能会丢失"。在美国,大多数大学生在毕业一年左右时会丢失他们的* .edu电子邮件地址。如果您的电子邮件地址来自您正在支付的域名,并且您停止付款,则该电子邮件地址会消失。我想像电子邮件地址可能会被提供给新用户。这是否造成难以承受的负担取决于应用程序。
缺点
- 用户应该可以更改电子邮件地址。不适合主键
可以更改SQL数据库中的所有值。如果您的环境不能及时让您的dbms尊重ON UPDATE CASCADE声明,那么它是不合适的。我的环境呢。 (但我在不太好的非共享硬件上运行PostgreSQL。)YMMV。
用户名栏
赞成
- a" natural"主键
- 减少表格连接
- 更简单,更自然"查询
更少的联接是重要的一点。我一直在咨询演出,我已经看到盲目使用ID号码让人们用40多个连接编写查询。明智地使用自然键消除了高达75%的自然键。
始终使用代理键作为外键的目标(除非是Oracle)或始终使用自然键作为目标并不重要。思考很重要。
缺点
- varchar列在连接表时速度较慢
- varchar列上的索引比int列索引
更紧凑
如果不对该声明进行限定,您无法真正说明加入varchar()会更慢。事实是,尽管varchar()上的大多数联接比id号上的联接慢,但它们并不一定非常慢以至于您无法使用它们。如果一个查询需要4ms的id号,而6ms的varchar(),我不认为这是取消varchar()资格的一个很好的理由。此外,使用自然键将消除大量连接,因此整体系统响应可能更快。 (在其他条件相同的情况下,40个4ms连接将表现不到10个6ms连接。)
我无法回想起数据库职业生涯中的任何情况(25年以上),其中索引的宽度是选择外键目标的决定性因素。
external_customer列
优点
- 可以作为客户的外部参考而不保留任何信息(也许可以使用不可编辑的用户名?)
实际上很少有系统允许我更改用户名。大多数人会让我改变我的真实姓名(我认为),但不是我的用户名。我认为不可编辑的用户名是完全合理的。
答案 1 :(得分:4)
通常,Web应用程序会尝试使其数据库架构远离客户 - 包括主键。我认为您正在将您的架构设计与身份验证方法混为一谈 - 即使您的数据库设计使用整数来唯一标识它们,也无法阻止您允许用户使用其电子邮件地址登录。
每当我设计这样的系统时,我都使用了ID列 - 主键的整数或GUID。它很快,不会因为讨厌的现实生活情况而改变,并且是开发人员熟悉的习惯用语。
我已经为手中的应用程序制定了最佳身份验证方案 - 大多数人希望这些天能够使用他们的电子邮件地址登录,所以我会坚持这一点。当然,您也可以让他们使用Facebook,Twitter或Google帐户登录。与我的主键无关,但是......
答案 2 :(得分:0)
我认为使用用户名栏你也有这个缺点:
因此,出于同样的原因,您不会使用该电子邮件,我将不会使用该用户名。对我来说,内部用户整数id是最好的方法。