MySQL【基础】篇:什么是MySQL、主键和外键、三大范式、DDL、DML、DDL、DCL...

什么是 MySQL?

难度:简单

【面试官来袭】第二弹之MySQL基础篇

MySQL是一个传统的 RDBM 数据库 ,也就是关系型数据库 ,广泛应用于 OLTP 场景

追问: OLTP 和 OLAP 的区别

难度:简单

OLTP(在线事务处理) 是++传统的关系型数据库++的主要应用,用于基本的、日常的事务处理,例如银行的交易记录;

OLAP(在线分析处理) 是++数据仓库系统++ 的主要应用,支持++复杂的分析操作++,侧重决策支持,并且提供了直观易懂的查询结果。最常见的应用就是复杂的动态报表系统。

总结下来,就是说:

  • OLTP 面向日常的业务操作,强调"小、快、准"。
  • 而 OLAP 面向数据分析,强调"大、重、广"。

OLTP,Online Transaction Processing,在线事务处理。

主要面向++业务系统++,比如下单、支付、库存更新这类操作。

特点是:

  • 请求量大、并发高
  • 每次操作很小、很快
  • 强调实时性、一致性、可靠性
  • 底层通常用行存储、索引优化、事务隔离等提高性能
    场景就是银行转账、电商下单、App 登录这些典型业务动作。

OLAP,Online Analytical Processing,在线分析处理。

主要用于++数据分析++,比如报表、数据统计、趋势分析。

特点是:

  • 查询量少,但一次查询非常重
  • 更关注吞吐量与分析速度
  • 对实时性要求没那么高
  • 底层偏向列存储、分布式存储、批处理
    场景就是 BI 报表、数据仓库、年销售分析等。

一句话总结:

  • OLTP 面向业务操作,强调"小、快、准";
  • OLAP 面向分析统计,强调"大、重、广"。

主键和外键是什么?

主键 就是++表中的一个或多个字段++ ,用来++唯一标识一条记录++,不能重复,也不能为 NULL。

外键 就是++另一张表的主键,在当前表中被引用++。

  • 当前表中该字段的使用范围,取决于之前的表。
  • 外键主要是用来++维护表与表之间的++ ++数据一致性++。</font

分析:

主键和外键是关系型数据库 里保证**++数据唯一性++ ++关系一致性++**的两个重要概念。

  • 主键(Primary Key)就是++表里的一个或多个字段++,用来唯一标识一条记录 ,不能重复,也不能为 NULL。比如学生表的student_id字段,每个学生都有唯一 ID,用来区分不同记录。
  • 外键(Foreign Key) 是指 ++另一张表的主键++在当前表中被引用 。外键的作用是++建立表与表之间的关系++ ,并++保证数据的一致性++ 。

一句话总结:

主键负责标识唯一记录;外键负责维护表与表之间的引用关系,确保数据一致性。

示例:

1)user 表(用户表)

id(主键) name
1 张三
2 李四
3 王五

user 表中的 id 就是主键,每个用户都有唯一的 id。

2)order 表(订单表)

order_id user_id amount
1001 1 99
1002 3 299
1003 2 50

order 表中的** user_id 就是 外键**,user_id 引用了 user 表的主键 id

order 表中 user_id 的使用范围,取决于 user 表。

++为什么要有外键?++

这个问题等价于:如果没有外键,会发生什么?

在没有外键的情况,我们往 order 表中插入:

sql 复制代码
INSERT INTO order(user_id, amount)
VALUES (99999, 100);

order 表中会多一条下列的记录:

order_id user_id amount
1004 9999 100

可是 user 表中根本没有 id = 9999 的人,订单找不到对应的用户,这就属于孤儿订单

上述情况也就属于数据不一致

而有外键的情况下,****我们往 order 表中插入:

sql 复制代码
INSERT INTO order(user_id, amount)
VALUES (99999, 100);

数据库就会直接报错:

go 复制代码
cannot add or update a child row: a foreign key constraint fails

因为 外键要求 user_id 必须在 user 表里存在。

一张表一定会有主键吗?

是的,一张表一定会有主键,用来唯一标识一行数据。

如果开发者没有手动设置主键,MySQL 的 InnoDB

引擎也会自动帮我们生成一个隐藏主键 row_id.

追问:InnoDB 是如何自动选择主键的?(3条规则)

InnoDB 自动选择主键遵循三个规则:

  1. 如果开发者给表手动指定了主键,那就用这个手动指定的。
  2. 没有指定主键,但有唯一索引,并且所有字段都非 NULL,那就用这个唯一索引当主键。
  3. 如果以上都没有,就自动生成一个 6 字节的 row_id 作为隐藏主键。

追问: 隐藏主键是什么?

隐藏主键 就是** InnoDB 自动给你补的一个 内部行标识,用来当 聚簇索引的主键。** 当你没有主动设置主键的时候,InnoDB

也必须有一个唯一标识来组织数据页,于是它会自动生成一个看不见的主键,这就是隐藏主键。 这个字段你在表结构里看不到,但在数据页里确实存在。

追问:InnoDB 为什么必须要主键?(聚簇索引原因)

因为InnoDB 的表是按照主键顺序存储的,这是典型的聚簇索引结构
数据行存储在主键索引的叶子节点上,所以每一行都必须有主键作为定位依据。

如果没有主键,InnoDB

根本没法构建聚簇索引,也没法在页内部快速定位记录,所以它必须选一个字段作为主键,就算开发者不设置也会自动生成。

一句话总结:InnoDB 的存储格式决定它必须要主键。

++追问:自动生成的 row_id 长什么样?++_

自动生成的 row_id 是个 6 字节(48 bit)的整数,递增生成,不会重复。 这个字段不会出现在表结构里,只存在于 InnoDB

的数据页里,用来唯一标识行。

  • 不是你能看到的字段
  • 不是 int,也不是 bigint
  • 不会通过 SQL 直接访问
  • 只在物理存储层使用

怎么查看有多少个 SQL 语句在执行?

可以用 SHOW PROCESSLIST 命令来查看当前正在执行的 SQL。

这个命令会列出++当前数据库里的活动线程++,包括执行中的 SQL、等待状态、连接信息等。

需要注意的是:

  • 普通用户只能看到自己的线程
  • **root 或有 PROCESS 权限的用户 **才能看到所有会话的执行情况。

数据库的三大范式是什么?

第一范式: 要求所有字段都是++不可再分的原子数据项++,强调的是列的原子性,

第二范式: 要求++非主键字段必须"++ ++完全依赖++ ++"主键++ ,++而不是"++ ++部分依赖++ ++"++

第二范式主要就是为了解决"联合主键导致的部分依赖问题"。

第三范式: ++非主键字段之间不能++ ++传递依赖++ ++,也就是说非主键字段不能相互依赖++ ,++非主键字段只能++ ++直接依赖++ ++于主键字段++。

在实际开发中没必要严格遵循三大范式,而是在++性能和一致性之间++找到平衡。

分析: 数据库的三大范式

数据库的三大范式是数据库设计中常见的++规范化原则++ ,主要用于++减少冗余、避免异常更新、提升数据一致性++。

第一范式(1NF)------字段必须不可再分(原子性

核心要求:

  • 每个字段必须是不可再拆分的最小数据项。
  • 即字段值不能再继续拆成多个部分。

示例:

学号 姓名 性别 出生年月日

"出生年月日"如果还能拆成++出生年++ 、++出生月++ 、++出生日++ → 违反 1NF。

**如何满足 1NF?**拆成:出生年、出生月、出生日。


第二范式(2NF)------非主键字段必须"完全依赖"主键,而不是"部分依赖"

第二范式就是为了解决"联合主键导致的部分依赖问题"的。

示例:

学号 课程号 姓名 学分

这张表的使用的是联合主键,主键 =(学号,课程号)

**为什么要设置联合主键? **

因为:

  • 一个学生可以选多门课
  • 一门课也可以被很多学生选

因此要唯一标识一条"学生选课关系",必须用:

同一个"学号 + 课程号"组合,才能唯一标识一条记录。

上面的这个表不符合 2NF,因为:

  • "姓名"只依赖"学号",不依赖"课程号",即不依赖整个主键。
  • "学分"只依赖"课程号",不依赖"学名",即不依赖整个主键。

正确做法------拆表,将上述表拆成三张表:

表1:学生表(Student)

学号 姓名

表2:课程表(Course)

课程号 学分

表3:选课关系表(StudentCourse)

学号 课程号

第三范式(3NF)------非主键字段之间不能存在传递依赖

√ 正确的依赖关系:直接依赖 ,就是++非主键只依赖主键++ ;
× 错误的依赖关系:传递依赖,非主键不是直接依赖主键,而是依赖另一个非主键,"绕了一圈"最后依赖关系才传递到主键。

示例:

学号(A) 姓名 年龄 所在学院(B) 学院电话©

传递关系是:学号A → 所在学院B → 学院电话C

C 不是直接依赖 A,是通过 B 间接依赖 A → 这就是传递依赖 → 违反第三范式

如何改?

拆成两张表:

1)学生:学号、姓名、年龄、所在学院

2)学院:学院名、学院电话


三范式总结表

范式 存在问题 解决问题
1NF 字段可再拆 字段要原子化
2NF 部分依赖 非主键字段必须完全依赖主键
3NF 传递依赖 非主键字段不能依赖其他非主键字段

💡注意:范式判断是++设计层面的逻辑++,数据库不能自动推断是否违反了三大范式。

因为数据库无法知道:

  • 哪个字段是"业务上"的主键
  • 哪些字段"业务上"应该依赖谁
  • 哪些字段"业务上"有计算关系

追问1:范式设计是为了解决什么问题?

数据库范式的目的,是为了解决几类典型的数据问题:

  1. 数据冗余------避免同一份数据被重复存多次,浪费空间,也容易产生不一致。
  2. 数据不一致(更新异常)------当同一份信息存多处、更新时只改了一部分,就会出现数据不一致的问题;范式化通过拆分表来保证更新一致性。
  3. 插入异常------某些字段因为结构不合理导致必须填冗余字段,否则插不进去;范式避免这种情况。
  4. 删除异常------删除一条记录时可能误删其他重要信息;范式通过拆分相关数据避免级联丢失。

简单说,范式就是通过减少冗余、消除依赖,保证数据的一致性、完整性和可维护性。

追问2:范式设计有什么缺点?

范式化的确能减少冗余、保持数据一致性,但它也有明显的缺点。 因为范式会把数据拆成多个表,所以很多查询都需要做 联表查询(JOIN)

这在实际业务中成本很高:查询慢、索引利用率低,而且联表查询很不适合做 分库分表,会让架构复杂度增加。

所以在真实项目里,很多时候我们会做
反范式设计。也就是说,适当冗余一些字段,让查询直接在单表内完成,避免大量的联表查询,提高性能和可扩展性。

所以,在实际开发中,++性能和一致性需要平衡,而不是盲目追求范式化++。

DDL、DML、DDL、DCL 分别是什么?

分析:以上三个问题,是针对数据库操作分类的考察。我们不能只知道增删查改,还要知道它们属于哪类。

从事务的角度来看,数据库的操作主要分成四类:

  1. DDL(Data Definition Language)数据定义语言

    1. 用来++定义数据库对象++,比如创建数据库、创建表、删除表等。
  2. DML(Data Manipulation Language)数据操作语言

    1. 用来++对表里的数据进行++增删改++++
  3. DQL(Data Query Language)数据查询语言

    1. 用来++查询数据++ ,比如我们最常写的 SELECT
  4. DCL(Data Control Language)数据控制语言

    1. 用来++控制数据库用户的权限++,比如创建用户、授权用户、回收权限。
    2. 比如:GRANTREVOKE

总结: DDL 管结构、DML 改数据、DQL 查数据、DCL管权限。

相关推荐
2022.11.7始学前端1 小时前
n8n第二节 实现小卖部商品财务报表自动化生成
java·n8n
y***n6141 小时前
SpringCloud系列教程:微服务的未来(十四)网关登录校验、自定义过滤器GlobalFilter、GatawayFilter
java·spring cloud·微服务
p***s911 小时前
java进阶1——JVM
java·开发语言·jvm
我是苏苏1 小时前
C#基础:如何创建一个类库并且封装成DLL
开发语言·c#
杜子不疼.1 小时前
【Linux】进程概念(六):地址空间核心机制
linux·运维·服务器
g***96901 小时前
在Nginx上配置并开启WebDAV服务的完整指南
java·运维·nginx
中工钱袋1 小时前
Spring Task 使用指南
java·spring boot·spring
伯远医学1 小时前
CUT&RUN
java·服务器·网络·人工智能·python·算法·eclipse
APIshop1 小时前
1688 拍立淘接口 item_search_img 返回值超细说明
linux·运维·服务器