MySQL基础
两张表怎么进⾏连接?
可以通过内连接 inner join、外连接 outer join、交叉连接 cross join 来合并多个表的查询结果
内连接可以用来找出两个表中共同的记录,相当于两个数据集的交集
SELECT users.name, orders.order_id
FROM users
INNER JOIN orders ON users.id = orders.user_id;只有两表中都存在 user_id 的记录才会出现在查询结果中
左连接和右连接可以用来找出两个表中不同的记录,相当于两个数据集的并集。两者的区别是,左连接会保留左表中符合条件的所有记录,右连接则刚好相反
即如果右表中有匹配的记录,就返回匹配的记录,否则就用 null 填充
SELECT users.id, users.name, orders.order_id
FROM users
LEFT JOIN orders ON users.id = orders.user_id;说一下数据库的三大范式?
第一范式,确保表的每一列都是不可分割的基本数据单元
第二范式,要求表中的每一列都和主键直接相关
第三范式,非主键列应该只依赖于主键列
建表的时候需要考虑哪些问题?
首先需要考虑表是否符合数据库的三大范式,确保字段不可再分,消除非主键依赖,确保字段仅依赖于主键等。
然后在选择字段类型时,应该尽量选择合适的数据类型。
在字符集上,尽量选择 utf8mb4,这样不仅可以支持中文和英文,还可以支持表情符号等。
当数据量较大时,比如上千万行数据,需要考虑分表。比如订单表,可以采用水平分表的方式来分散单表存储压力。
为什么需要三大范式?
核心目标是 减少数据冗余,避免三种异常:
- 更新异常:修改一处数据需改多处(如改产品名称,所有订单都要改)。
- 插入异常:某些信息无法单独插入(如新增产品但暂无订单,产品信息插不进订单表)。
- 删除异常:删除一条记录意外删除其他信息(如删除最后一个订单,产品信息也被删)。
不遵循三大范式的场景
例子:电商订单列表页
- 需求:快速展示订单中的 「商品名称」「商品单价」(用户高频访问,性能要求高)。
- 按 3NF 设计:订单表(订单 ID,商品 ID)+ 商品表(商品 ID,名称,单价),查询时需关联两张表。
- 实际优化:直接在订单表中冗余 「商品名称」「商品单价」,避免关联查询,牺牲少量冗余换取查询速度。
原因:高并发场景下,关联查询(JOIN)耗时,冗余存储可减少数据库 IO,提升响应速度。此时 「违反范式」 是权衡性能后的合理选择。
varchar 和 char 的区别
varchar 是可变长度的字符串类型,原则上最多可以容纳 65535 个字符,但考虑字符集,以及 MySQL 需要 1 到 2 个字节来表示字符串长度,所以实际上最大可以设置到 65533
char 是固定长度的字符类型,当定义一个 CHAR(10) 字段时,不管实际存储的字符长度是多少,都只会占用 10 个字符的空间。如果插入的数据小于 10 个字符,剩余的部分会用空格填充
in 和 exists 的区别
IN 的执行逻辑:子查询优先,结果集匹配
- 第一步:先执行子查询,得到一个 「单列值列表」(如
(1,2,3)),并临时存储; - 第二步:主查询遍历每一条记录,判断 「主表字段值是否在子查询的列表中」(类似
value IN (a,b,c)的等值判断);
EXISTS 的执行逻辑:主查询驱动,关联判断
- 第一步:先执行主查询,取出一条记录;
- 第二步:将这条记录的字段(如
u.id)传入子查询,判断子查询是否能找到匹配记录(如o.user_id = u.id); - 第三步:若子查询返回至少一条记录(存在匹配),则主查询保留这条记录;否则丢弃,继续遍历主查询下一条;