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

inf*_*oop 7 mysql database-design primary-key surrogate-key

我试图在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
Run Code Online (Sandbox Code Playgroud)

我正面临主键候选列的以下问题:

Id列

优点

  • 没有商业意义(稳定的主键)
  • 更快的表连接
  • 压缩指数

缺点

  • 不是"自然"的关键
  • 所有属性表必须与"主"用户表连接,因此不能进行非加入直接查询
  • 导致较少的"自然"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列

利弊

  • 可以用作客户的外部参考并且不保留任何信息(可能会使用不可编辑的用户名?)

    缺点

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

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

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

Mik*_*ll' 11

我对你的一些分析没什么可说的.如果我削减了你的一些优点或缺点,那只意味着我认为我没有任何有用的东西可以添加.

Id列

优点

  • 没有商业意义(稳定的主键)
  • 更快的表连接
  • 压缩指数

首先,声明为NOT NULL UNIQUE的任何列或列集都具有主键的所有属性.您可以将它们中的任何一个用作外键引用的目标,这就是所有这一切的真正含义.

在您的情况下,您的结构允许4列成为外键引用的目标:id,username,email和external_customer_id.您没有使用相同的一个所有的时间.为90%的FK引用使用id可能是有意义的,并通过电子邮件发送10%的FK引用.

稳定性与列是否具有商业含义无关.稳定性与价值可能发生变化的频率和在何种情况下有关.除非你运行Oracle,否则"稳定"并不意味着"不可变".(Oracle无法执行ON UPDATE CASCADE.)

根据您的表结构和索引,自然键可能会执行得更快.自然键使一些连接不必要.在构建生产数据库之前,我做过测试.我们可能需要几十年时间才能达到连接ID号码的能力将超过更少的连接和自然键.我已经在SO或DBA上写过这些测试.

您还有其他三个唯一索引.(对你有好处.我认为构建数据库的人中至少有90%没有那么正确.)因此,ID号的索引不仅比这三者中的任何一个更紧凑; 它也是一个额外的指数.(在此表中.)

电子邮件列

优点

  • 没有

电子邮件地址可以被认为是稳定且独特的.您无法阻止人们共享电子邮件地址,无论它是否是外键引用的目标.

但电子邮件地址可能会"丢失".在美国,大多数大学生在毕业一年左右时会丢失他们的*.edu电子邮件地址.如果您的电子邮件地址来自您正在支付的域名,并且您停止付款,则电子邮件地址会消失.我想像这样的电子邮件地址可能会被提供给新用户.这是否造成难以忍受的负担取决于应用程序.

缺点

  • 用户应该能够更改电子邮件地址.不适合主键

可以更改SQL数据库中的所有值.如果您的环境不允许您的dbms及时授予ON UPDATE CASCADE声明,那么它是不合适的.我的环境呢.(但我在体面的非共享硬件上运行PostgreSQL.)YMMV.

用户名栏

优点

  • 一个"自然的"主键
  • 减少表连接
  • 更简单,更"自然"的查询

更少的联接是重要的一点.我一直在咨询演出,在那里我看到盲目使用ID号码让人们用40多个连接编写查询.明智地使用自然键消除了高达75%的自然键.

始终使用代理键作为外键的目标(除非是Oracle)或始终使用自然键作为目标并不重要.思考很重要.

缺点

  • 连接表时varchar列较慢
  • varchar列上的索引比int列索引更紧凑

你无法真正说明加入varchar()的速度较慢而没有对该声明进行限定.事实是,尽管大多数联接在VARCHAR()不是加入的ID号慢,他们未必就这么慢,你可以不使用它们.如果查询需要4ms的id号,6ms的varchar(),我认为这不是取消varchar()资格的好理由.此外,使用自然键将消除大量连接,因此整体系统响应可能更快.(在其他条件相同的情况下,40个4ms的连接将表现不到10个6ms连接.)

我记不起我的数据库事业(25年以上)中的任何情况,其中索引的宽度是选择外键目标的决定性因素.

external_customer列

利弊

  • 可以用作客户的外部参考并且不保留任何信息(可能会使用不可编辑的用户名?)

实际上很少有系统允许我更改用户名.大多数人会让我改变我的真实姓名(我认为),但不是我的用户名.我认为不可编辑的用户名是完全合理的.