MySQL学习笔记:索引和数据库设计

索引

数据库的索引,可以理解成字典的目录,是为了方便数据库快速查询数据用的。

为什么创建索引,查询速度会更快?创建索引的过程,是创建数据结构,提高查询速度。举个例子,如果学生表有100万条输入,如下:

student_id student_name
1 张三
2 李四
... ...
1,000,000 王二麻子
假如我要查询student_name为王二麻子的记录,则数据库需要遍历所有行,即全表查询,最坏情况下要查询100万次才能找到我需要的数据,这样查询速度会很慢。

如果创建索引,数据库根据引擎的不同,会通过B+tree(MySQL innnoDB默认)、哈希表等数据结构的方式构建索引。比如用B+tree,要查询student_name为王二麻子的记录,只需要几次就可以查到。

有哪几种索引?

索引类型有主键索引(PRIMARY KEY)、唯一索引(UNIQUE)、普通索引(KEY/VALUE)、全文索引(FULLTEXT)。

  1. 主键索引(PRIMARY KEY):特殊的唯一索引,一张表只有一个。
  2. 唯一索引(UNIQUE):索引列值必须唯一。
  3. 普通索引(KEY/VALUE):最常用的索引,没有约束。
  4. 全文索引(FULLTEXT):用于全文搜索,适用于文本列(TEXT类长文本)。

当我们在建表时定义好主键,MySQL会自动为主键列创建一个名为PRIMARY的唯一索引;

当我们在创建唯一约束时(约束列的值必须是唯一的),MySQL会自动为该列创建一个唯一索引;

当我们在创建外键约束是(约束列的值必须在被引用的表中存在),MySQL会自动为外键列创建索引(假如还没有索引的话),这是为了确保在更新或删除父表(被引用的表)中的行时,能够快速检查子表(引用表)中是否存在对应的行,从而提高检查的效率。

当然,最常见的是我们自己自定义创建索引,以提高查询效率。

创建索引的目的是为了提高速度,但是创建索引需要额外的资源开销,更新索引也需要时间,因此,创建索引有以下注意事项:

  1. 数据表记录比较少,不建议创建索引,因为哪怕是遍历查询也很快
  2. 经常更新的列谨慎创建索引,因为每次更新都需要去更新数据结构,需要消耗计算资源

数据库设计

数据库设计是指设计满足业务需求的数据库表,数据库设计的流程一般是:

  1. 分析业务需求:根据产品原型、产品文档,分析业务所需要存取的数据
  2. 数据库概要设计:设计需要创建的数据库、表、字段,绘制数据表关系图
  3. 创建数据库表:一般通过可视化工具,创建数据库表和字段

为了减少数据冗余、提高数据一致性、避免数据更新异常,数据库设计有三大范式,通常建议数据库设计时遵守。

  1. 第一范式:确保每一列的原子性。第一范式要求每一列都是不可再分的最小单元。比如某列字段名为学院办公室,存储示例"科技楼102室"。则可以拆分成字段:楼栋("科技楼")、办公室("102室")
  2. 第二范式:前提必须满足第一范式。第二范式规定数据表中所有非主键必须完全依赖于整个主键,而不能只依赖于主键的一部分。这个范式适用于主键由多个字段组成的情况。如果一个字段只能由部分主键就能决定,则需要拆表。
  3. 第三范式:前提必须满足第一范式和第二范式。任何非主键字段之间不能有依赖关系,即非主键字段必须直接依赖于主键,而不能通过其他非主键字段间接依赖。

在实际开发过程中,往往需要考虑到满足业务需求的数据存取性能,会违反三大范式。比如:一个学生表和班级表,两者通过class_id做关联,正常设计表如下:

student_id student_name class_id
1 张三 NULL
2 李四 1
3 王五 2
4 赵六 2
class_id class_name
1 1班
2 2班
3 3班

正常情况下,如果要查询学生的所在班级,要通过两个表联表查询。如果业务需求要频繁操作,在数据量比较大时候,可以创建索引提高查询速度。另外,也可以将class_name存储到学生表,这样避免了联表查询操作。显然,这违反了三大范式,这是一种以空间换时间的反范式设计。

student_id student_name class_id class_name
1 张三 NULL NULL
2 李四 1 1班
3 王五 2 2班
4 赵六 2 2班
相关推荐
flashier2 小时前
ESP32学习笔记_WiFi(3)——HTTP
网络·笔记·单片机·网络协议·学习·http·esp32
70asunflower2 小时前
Zotero论文阅读标记颜色框架
人工智能·学习·考研
eWidget2 小时前
从MongoDB到金仓数据库:一场零中断的国产化迁移实践
数据库·mongodb·kingbase·数据库平替用金仓·金仓数据库
xhbaitxl2 小时前
算法学习day29-贪心算法
学习·算法·贪心算法
HL_风神2 小时前
QT事件循环机制源码学习
开发语言·qt·学习
niceffking2 小时前
SQL(困难):计算用户的平均次日留存率
数据库·sql
zgl_200537792 小时前
源代码:ZGLanguage 解析SQL数据血缘 之 显示 MERGE SQL 结构图
数据库·数据仓库·hive·数据治理·etl·sql解析·数据血缘
__风__2 小时前
PostgreSQL timestamp类型说明
数据库·postgresql
im_AMBER2 小时前
消失的最后一秒:SSE 流式联调中的“时序竞争”
前端·笔记·学习·http·sse