第一章:数据库设计基础

说实话,我见过太多系统上线后跑得比蜗牛还慢,最后查下来,根子都在数据库设计上。你想想看,地基没打好,后面再怎么优化SQL,效果都有限。今天咱们就来聊聊数据库设计的那些基本功。

1.1 理解关系型数据库

关系型数据库,说白了就是一张张表格的集合。每张表里存着同一类东西,比如用户表、订单表。表跟表之间还能通过某些字段关联起来。

我刚开始做项目时,有个同事把所有数据都塞进一张大表里。用户信息、订单记录、商品详情,全混在一起。结果呢?查询慢得要命,数据还经常不一致。后来我帮他重新设计了表结构,性能直接提升了10倍。

关系型数据库的核心就三点:

  • 表(Table):存储数据的容器,类似Excel表格
  • 行(Row):一条完整的数据记录
  • 列(Column):数据的一个属性字段
我的习惯:设计表之前,先画一张ER图。把实体、属性、关系理清楚,再动手建表。这样能避免很多后期返工。

1.2 ER图:设计前的蓝图

ER图(实体-关系图)是数据库设计的视觉工具。它用图形的方式,把业务需求转化成数据结构。

举个例子,一个简单的电商系统:

  • 实体:用户、商品、订单
  • 属性:用户名、价格、下单时间
  • 关系:用户下订单、订单包含商品

画ER图时,我习惯用矩形表示实体,椭圆表示属性,菱形表示关系。嗯,这里要注意:关系有三种类型——一对一、一对多、多对多。

避坑指南:我曾经在一个项目中,没画ER图就直接建表。结果做到一半,发现订单和商品的关系搞反了。改起来那叫一个痛苦,数据迁移、代码调整,折腾了两天。从那以后,ER图成了我的标配。

1.3 范式化设计:1NF、2NF、3NF

范式化设计,说白了就是一套规则,用来减少数据冗余,保证数据一致性。我见过很多新手觉得范式化太麻烦,结果数据越存越乱。

第一范式(1NF)

每个字段都是不可分割的原子值。说白了,就是一张表里不能有「列表」字段。

举个反例:

-- 违反1NF的设计
CREATE TABLE student (
    id INT,
    name VARCHAR(50),
    courses VARCHAR(200)  -- 存了"数学,英语,物理"
);

正确的做法:

-- 符合1NF的设计
CREATE TABLE student (
    id INT,
    name VARCHAR(50)
);

CREATE TABLE enrollment (
    student_id INT,
    course_name VARCHAR(50)
);

第二范式(2NF)

在1NF的基础上,所有非主键字段必须完全依赖于主键。不能有部分依赖。

我记得有个项目,订单表里同时存了商品ID和商品价格。但商品价格其实只依赖于商品ID,不依赖于订单ID。这就违反了2NF。

注意:违反2NF会导致数据更新异常。比如商品涨价了,你得把所有订单里的价格都改一遍,很容易漏改。

第三范式(3NF)

在2NF的基础上,非主键字段不能传递依赖于主键。说白了,就是不能有「A决定B,B决定C」这种链条。

举个例子:

-- 违反3NF的设计
CREATE TABLE order (
    order_id INT PRIMARY KEY,
    customer_id INT,
    customer_name VARCHAR(50),  -- customer_name依赖于customer_id,不直接依赖于order_id
    customer_phone VARCHAR(20)
);

正确的做法是把客户信息单独拆成一张表:

-- 符合3NF的设计
CREATE TABLE customer (
    customer_id INT PRIMARY KEY,
    customer_name VARCHAR(50),
    customer_phone VARCHAR(20)
);

CREATE TABLE order (
    order_id INT PRIMARY KEY,
    customer_id INT,
    FOREIGN KEY (customer_id) REFERENCES customer(customer_id)
);

1.4 主键与外键设计原则

主键和外键,是表与表之间建立关系的桥梁。设计得好,查询效率高;设计得不好,各种坑等着你。

主键设计原则

  • 唯一性:主键值必须唯一,不能重复
  • 非空:主键不能为NULL
  • 稳定性:主键值一旦确定,最好不要修改
  • 简洁性:尽量用整数类型,别用字符串
我的建议:能用自增ID就用自增ID。别用业务字段做主键,比如身份证号、手机号。为什么?因为业务字段可能会变,变了你就得改所有关联表,那场面...你懂的。

外键设计原则

  • 类型一致:外键字段类型必须和关联的主键类型一致
  • 索引优化:外键字段建议加索引,提升关联查询性能
  • 级联操作:谨慎使用级联删除,搞不好会删掉一大片数据

我曾经接手过一个系统,外键字段没加索引。有个关联查询跑了30秒,加上索引后,瞬间变成0.1秒。你想想看,这差距有多大。

核心总结:

  1. 关系型数据库就是表格的集合,表之间通过关系连接
  2. ER图是设计前的必备工具,别偷懒
  3. 1NF保证原子性,2NF消除部分依赖,3NF消除传递依赖
  4. 主键用自增ID,外键加索引,类型要一致

好了,这一章的内容就到这儿。下一章咱们聊聊索引的设计与优化,那可是SQL优化的重头戏。