表结构设计

三个范式:

  • 一范式要求所有属性都是不可分的基本数据项;
  • 二范式解决部分依赖;
  • 三范式解决传递依赖。

真实的业务场景是工程实现,表结构设计做好以下几点就已经足够:

  • 每张表一定要有一个主键(方法有自增主键设计、UUID 主键设计、业务自定义生成主键);
  • 消除冗余数据存在的可能。

不用过于追求所谓的数据库范式准则,甚至有些时候,我们还会进行反范式的设计。

自增主键设计

主键用于唯一标识一行数据,所以一张表有主键,就已经直接满足一范式的要求了

但你要注意,使用 BIGINT 的自增类型作为主键的设计仅仅适合非核心业务表,比如告警表、日志表等。真正的核心业务表,一定不要用自增键做主键,主要有 6 个原因:

  • 自增存在回溯问题;
  • 自增值在服务器端产生,存在并发性能问题;
  • 自增值做主键,只能在当前实例中保证唯一,不能保证全局唯一
  • 公开数据值,容易引发安全问题,例如知道地址http://www.example.com/User/10/,很容猜出 User 有 11、12 依次类推的值,容易引发数据泄露;
  • MGR(MySQL Group Replication) 可能引起的性能问题;
  • 分布式架构设计问题。

虽然,我们可以调整参数 innodb_autoinc_lock_mode获得自增的最大性能,但是由于其还存在上述 5 个问题。因此,在互联网海量并发架构实战中,我更推荐 UUID 做主键或业务自定义生成主键。

UUID主键设计

UUID(Universally Unique Identifier)代表全局唯一标识 ID。显然,由于全局唯一性,你可以把它用来作为数据库的主键。

CREATE TABLE User (

  id  BINARY(16) NOT NULL,

  name VARCHAR(255) NOT NULL,

  sex CHAR(1) NOT NULL,

  password VARCHAR(1024) NOT NULL,

  money INT NOT NULL DEFAULT 0,

  register_date DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),

  last_modify_date DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),

  uuid CHAR(36) AS (BIN_TO_UUID(id)),

  CONSTRAINT chk_sex CHECK (sex = 'M' OR sex = 'F'),

  PRIMARY KEY(id)

);

而且由于 UUID 能保证全局唯一,因此使用 UUID 的收益远远大于自增ID。可能你已经习惯了用自增做主键,但在海量并发的互联网业务场景下,更推荐 UUID 这样的全局唯一值做主键。

比如,我特别推荐游戏行业的用户表结构设计,使用 UUID 作为主键,而不是用自增 ID。因为当发生合服操作时,由于 UUID 全局唯一,用户相关数据可直接进行数据的合并,而自增 ID 却需要额外程序整合两个服务器 ID 相同的数据,这个工作是相当巨大且容易出错的。

业务自定义生成主键

现在你只需要牢记:分布式数据库架构,仅用 UUID 做主键依然是不够的。 所以,对于分布式架构的核心业务表,我推荐类似如下的设计,比如:

PK = 时间字段 + 随机码(可选) + 业务信息1 + 业务信息2 ......

消除冗余

消除冗余也是范式的要求,解决部分依赖和传递依赖,本质就是尽可能减少冗余数据。

当然了,无论是自增主键设计、UUID主键设计、业务自定义生成主键、还是消除冗余,本质上都是遵循了范式准则。但是在一些其他业务场景下,也存在反范式设计的情况。

反范式设计

通常我们会在 OLAP 数据分析场景中使用反范式设计,但随着 JSON 数据类型的普及,MySQL 在线业务也可以进行反范式的设计。

总结

总的来说,范式是偏数据库理论范畴的表结构设计准则,在实际的工程实践上没有必要严格遵循三范式要求,在 MySQL 海量并发的工程实践上,表结构设计应遵循这样几个规范:

  • 每张表一定要有一个主键;
  • 自增主键只推荐用在非核心业务表,甚至应避免使用;
  • 核心业务表推荐使用 UUID 或业务自定义主键;
  • 一份数据应尽可能保留一份,通过主键关联进行查询,避免冗余数据;
  • 在一些场景下,可以通过 JSON 数据类型进行反范式设计,提升存储效率;

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值