前语

最近有不少前端和测验转Go的朋友在私信我:怎样做好表结构规划?

我们关心的问题阳哥有必要整理出来,期望对我们有帮助。

先说定论

这篇文章介绍了规划数据库表结构应该考虑的4个方面,还有高雅规划的6个准则,举了一个比方共享了我的规划思路,为了进步功能咱们也要从多方面考虑缓存问题。

收成最大的仍是和我们的沟通评论,总结一下:

  1. 首要,必定要先搞清楚事务需求。比方我的比方中,假如不需求灵敏设置,彻底能够写到装备文件中,并不需求独自规划外键。主表中直接保存各种挑选标签称号(留意保护的问题,要考虑到数据共同性)
  2. 数据库表结构规划必定考虑数据量和并发量,我的比方中假如数据量小,能够适作为冗余规划,下降事务复杂度。

4个方面

规划数据库表结构需求考虑到以下4个方面:

  1. 数据库范式:一般情况下,咱们期望表的数据契合某种范式,这能够确保数据的完整性和共同性。例如,第一范式要求表的每个特点都是原子性的,第二范式要求每个非主键特点彻底依赖于主键,第三范式要求每个非主键特点不依赖于其他非主键特点。

  2. 实体联系模型(ER模型):咱们需求先依据实践情况画出实体联系模型,然后再将其转化为数据库表结构。实体联系模型一般包含实体、特点、联系等要素,咱们需求将它们转化为表的形式。

  3. 数据库功能:咱们需求考虑到数据库的功能问题,包含表的巨细、索引的运用、查询语句的优化等。

  4. 数据库安全:咱们需求考虑到数据库的安全问题,包含表的权限、用户人物的设置等。

规划准则

在规划数据库表结构时,能够参考以下几个高雅的规划准则:

  1. 简单明了:表结构应该简单明了,防止过度复杂化。

  2. 共同性:表结构应该坚持共同性,例如命名规范、数据类型等。

  3. 规范化:尽可能将表规范化,防止数据冗余和不共同性。

  4. 功能:表结构应该考虑到功能问题,例如运用恰当的索引、防止全表扫描等。

  5. 安全:表结构应该考虑到安全问题,例如合理设置权限、防止SQL注入等。

  6. 扩展性:表结构应该具有必定的扩展性,例如预留字段、可扩展的联系等。

最后,需求提示的是,高雅的数据库表结构需求在实践中不断迭代和优化,不断满足实践需求和新的应战。

下面举个示例让我们更好的了解怎样规划表结构,怎样引入内存,有哪些优化思路:

问题描绘

初学后端,如何做好表结构设计?

如上图所示,红框中的视频挑选标签,应该怎样规划数据库表结构?除了前台挑选,还想支撑在办理后台灵敏装备这些挑选标签。

这是一个很好的运用场景,我们能够先自己想一下。不要着急看我的方案。

需求剖析

  1. 能够依据红框的标签挑选视频
  2. 其中归纳标签比较特别,和类型、区域、年份、艺人等不一样
  • 归纳是依据事务逻辑取值,并不需求入库
  • 类型、区域、年份、艺人等需求入库
  1. 规划表结构时要考虑到:
  • 便利获取标签信息,便利把标签信息缓存处理
  • 便利依据标签挑选视频,便利咱们写后续的事务逻辑

规划思路

  1. 归纳标签能够写到装备文件中(或许写在前端),这些信息不需求灵敏装备,所以不需求保存到数据库中
  2. 类型、区域、年份、艺人都规划独自的表
  3. 视频表中规划标签表的外键,便利视频列表挑选取值
  4. 标签信息写入缓存,进步接口响应速度
  5. 类型、区域、年份、艺人表也要支撑对数据排序,便利后期办理保护

表结构规划

视频表

字段 注释
id 视频主键id
type_id 类型表外键id
area_id 区域表外键id
year_id 年份外键id
actor_id 艺人外键id

其他和视频直接相关的字段(比方称号)我就省略不写了

类型表

字段 注释
id 类型主键id
name 类型称号
sort 排序字段

区域表

字段 注释
id 类型主键id
name 类型称号
sort 排序字段

年份表

字段 注释
id 类型主键id
name 类型称号
sort 排序字段

原以为年份字段不需求排序,要么是年份正序摆放,要么是年份倒序摆放,所以不需求sort字段。

仔细看了看需求,还有“10年代”仍是需求灵敏装备的呀~

艺人表

字段 注释
id 类型主键id
name 类型称号
sort 排序字段

表结构规划完了,别忘了缓存

缓存策略

首要这些不会频繁更新的挑选条件主张运用缓存:

初学后端,如何做好表结构设计?

  1. 比较常用的就是redis缓存
  2. 再进阶一点,假如你运用docker,能够把这些装备信息写入docker容器所在物理机的内存中,而不用恳求其他节点的redis,进一步下降网络传输带来的耗时损耗
  3. 挑选条件这类装备信息,客户端和服务端能够约好一个更新缓存的机制,客户端直接缓存装备信息,进一步进步功能

列表数据主动缓存

目前许多框架都是支撑主动缓存处理的,比方goframe和go-zero

goframe

能够运用ORM链式操作-查询缓存

示例代码:

package main
import (
	"time"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gctx"
)
func main() {
	var (
		db  = g.DB()
		ctx = gctx.New()
	)
	// 开启调试模式,以便于记载一切履行的SQL
	db.SetDebug(true)
	// 写入测验数据
	_, err := g.Model("user").Ctx(ctx).Data(g.Map{
		"name": "xxx",
		"site": "https://xxx.org",
	}).Insert()
	// 履行2次查询并将查询成果缓存1小时,并可履行缓存称号(可选)
	for i := 0; i < 2; i++ {
		r, _ := g.Model("user").Ctx(ctx).Cache(gdb.CacheOption{
			Duration: time.Hour,
			Name:     "vip-user",
			Force:    false,
		}).Where("uid", 1).One()
		g.Log().Debug(ctx, r.Map())
	}
	// 履行更新操作,并清理指定称号的查询缓存
	_, err = g.Model("user").Ctx(ctx).Cache(gdb.CacheOption{
		Duration: -1,
		Name:     "vip-user",
		Force:    false,
	}).Data(gdb.Map{"name": "smith"}).Where("uid", 1).Update()
	if err != nil {
		g.Log().Fatal(ctx, err)
	}
	// 再次履行查询,启用查询缓存特性
	r, _ := g.Model("user").Ctx(ctx).Cache(gdb.CacheOption{
		Duration: time.Hour,
		Name:     "vip-user",
		Force:    false,
	}).Where("uid", 1).One()
	g.Log().Debug(ctx, r.Map())
}

go-zero

DB缓存机制

go-zero缓存规划之持久层缓存

官方都做了具体的介绍,不作为本文的要点。

评论

我的方案也在我的技术沟通群里引起了我们的评论,也和我们共享一下:

Q1 冗余规划和共同性问题

发问: 一个表里做了这么多外键,假如我要查各自的称号,势必要相关4张表,对于这种存在多外键相关的这种表,要不要做冗余呢(直接在主表里冗余各自的称号字段)?要是确保共同性的话,就势必会影响功能,假如做冗余的话,又无法确保共同性

答复:

你看文章的上下文应该知道,文章想处理的是视频列表挑选问题。

你提到的这个场景是在视频详情信息中,假如要展现这些外键的称号怎样规划更好。

我的主张是这样的:

  1. 依据需求能够做恰当冗余,比方你的主表信息量不大,装备信息修正后同步修正冗余字段的本钱并不高。
  2. 或许像我文章中写的不做冗余规划,可是会把外键信息缓存,事务查询从缓存中取值。
  3. 或许将视频详情的查询成果全体进行缓存

仍是看具体需求,假如这些挑选信息不改变或许不需求手艺办理,乃至不需求规划表,直接写死在代码的装备文件中也能够。进一步下降DB压力,进步功能。

Q2 why规划外键?

发问:为什么要规划外键相关?直接写到视频表中不就行了?这么规划的意义在哪里?

答复:

  1. 关键问题是想处理办理后台灵敏装备
  2. 假如没有这个需求,咱们能够直接把挑选条件以装备文件的方式写死在程序中,下降复杂度。
  3. 站在我的视点:这个功能的挑选条件改变并不会很大,所以很懂你的意思。也主张像我2.中的方案去做,去和产品司理拉扯喽~

总结

这篇文章介绍了规划数据库表结构应该考虑的4个方面,还有高雅规划的6个准则,举了一个比方共享了我的规划思路,为了进步功能咱们也要从多方面考虑缓存问题。

收成最大的仍是和我们的沟通评论,总结一下:

  1. 首要,必定要先搞清楚事务需求。比方我的比方中,假如不需求灵敏设置,彻底能够写到装备文件中,并不需求独自规划外键。主表中直接保存各种挑选标签称号(留意保护的问题,要考虑到数据共同性)
  2. 数据库表结构规划必定考虑数据量和并发量,我的比方中假如数据量小,能够适作为冗余规划,下降事务复杂度

本文抛砖引玉,欢迎我们留言沟通。

一同学习

欢迎和我一同评论沟通:能够在私信我

也欢迎重视我的公众号:程序员升职加薪之旅

也欢迎我们重视我的,点赞、留言、转发。你的支撑,是我更文的最大动力!

文章首或尾句需求带关键词“本文正在参与「金石方案」