Web应用程序用户表主键:代理键vs用户名vs电子邮件vs客户ID

时间:2012-04-01 18:28:18

标签: mysql database-design primary-key surrogate-key

我正在尝试在MySQL中设计电子商务Web应用程序,但我在为用户表选择正确的主键时遇到问题。给出的示例只是一个示例示例。

enter image description here

用户表具有以下定义

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列

赞成

  • 没有商业意义(稳定的主键)
  • 更快的表连接
  • compacter index

缺点

  • 不是“自然”键
  • 所有属性表必须与“主”用户表连接,因此无法进行非加入直接查询
  • 导致较少的“自然”SQL查询
  • 泄漏信息:如果起始值为0,用户可以计算出注册用户的数量(更改起始值将其排序) ii)用户在time_X将配置文件注册为user_A,稍后一段时间,因为time_Y的user_B将能够轻松计算该时间段内的注册用户数((对于user_B的Id) - (user_A的Id)/(time_Y - time_X))

电子邮件专栏

赞成

缺点

  • 用户应该可以更改电子邮件地址。不适合主键

用户名栏

赞成

  • “自然”主键
  • 减少表格连接
  • 更简单,更“自然”的查询

缺点

  • varchar列在连接表时速度较慢
  • varchar列上的索引比int列索引
  • 更紧凑
  • 很难更改用户名,因为外键取决于值。解决方案:“同步”应用程序上的所有外键,不允许用户更改用户名,例如。用户应删除新的注册表

external_customer列

优点

  • 可以作为客户的外部参考而不保留任何信息(也许可以使用不可编辑的用户名?)

    缺点

  • 如果信息是自动增量(如果可能),
  • 可能会泄漏信息

  • 如果由于MySQL innodb引擎在同一个表中没有多个auto_increment列,自动增量代理ID已经在使用,则
  • 生成unqiue值会有问题
  

为a选择用户表主键时的常见做法是什么   可扩展的电子商务Web应用程序?所有反馈意见

3 个答案:

答案 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是最好的方法。

相关问题