Skip to content

3)建模与建表

  • 建模完成:理论上你已经完成了数据的组织设计,描述了数据结构及其相互关系。这是数据库设计的前期步骤,目的是为了理解数据如何在系统中流动与关联。
  • 建表完成:实际将建模过程中的设计转化为数据库中的表、字段、索引和约束等,这是一项具体的数据库操作,完成后数据库就可以实际存储和管理数据。

简而言之,建模完成可以看作是“理论上的建表”,而建表实际执行该设计,目的是创建一个可以在数据库中实现、查询和操作的结构。两者是紧密相连的,但建表是实现建模的具体步骤。

他们两者之间的顺序是:先建模,再建表

一、关系型数据库:建模建表案例分析

建模是数据库设计中非常重要的一个环节,目的是将业务需求转化为数据结构并设计出合理的表结构。这里我们将以一个电商系统为例来详细讲解建模过程。

案例:电商系统数据库建模

1. 业务需求分析

假设我们要设计一个简单的电商系统,系统的核心功能包括:

  • 用户注册和登录
  • 商品展示和管理
  • 购物车和订单管理
  • 支付和订单状态管理

2. 识别核心实体

根据业务需求,我们可以提取出系统的核心实体(数据对象),并为这些实体定义属性:

  • 用户(User):包括用户名、密码、邮箱等信息。
  • 商品(Product):包括商品名称、描述、价格、库存等。
  • 订单(Order):包括订单 ID、用户 ID、订单状态、支付状态等。
  • 购物车(Cart):包括用户 ID、商品 ID、数量等。

3. 确定实体之间的关系

接下来,我们需要分析各个实体之间的关系。常见的关系有“一对多”和“多对多”。

  • 用户与订单的关系:一个用户可以有多个订单(1:N 关系)。
  • 订单与商品的关系:一个订单中可以包含多个商品,一个商品也可以出现在多个订单中(N:M 关系),这通常需要一个关联表来表示。
  • 用户与购物车的关系:一个用户有一个购物车,而一个购物车可以有多个商品(1:N 关系)。

4. 绘制实体关系图(ER 图)

在了解了实体及其关系后,我们可以使用 ER 图 来表示这些信息。以下是这个电商系统的简化版 ER 图

  • User -- (1:N) --> Order
  • Product -- (N:M) --> Order (通过一个关联表 OrderItems
  • User -- (1:N) --> Cart
  • Cart -- (N:M) --> Product (通过一个关联表 CartItems

ER 图会如下所示:

+---------+         +--------+       +--------+
|  User   |   1:N  |  Order |  N:M  | Product|
+---------+         +--------+       +--------+
     |                 |
     |                 |
     |                 |
     v                 v
+---------+       +-------------+     +---------+
|   Cart  |  1:N |  OrderItems |  N:M | CartItems|
+---------+       +-------------+     +---------+

5. 确定数据表和字段

接下来,我们可以将这些实体和关系转化为数据表。为此,我们将每个实体转换为一张表,并确定每张表的字段。

User 表(用户表)

用户表存储用户的基本信息:

sql
CREATE TABLE Users (
  user_id INT AUTO_INCREMENT PRIMARY KEY,  -- 用户ID(主键)
  username VARCHAR(255) NOT NULL,          -- 用户名
  password VARCHAR(255) NOT NULL,          -- 密码
  email VARCHAR(255) NOT NULL,             -- 邮箱
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP  -- 创建时间
);
Product 表(商品表)

商品表存储商品的基本信息:

sql
CREATE TABLE Products (
  product_id INT AUTO_INCREMENT PRIMARY KEY,  -- 商品ID(主键)
  name VARCHAR(255) NOT NULL,                  -- 商品名称
  description TEXT,                            -- 商品描述
  price DECIMAL(10, 2) NOT NULL,               -- 商品价格
  stock INT NOT NULL,                          -- 库存
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 创建时间
);
Order 表(订单表)

订单表存储订单信息,包含用户和订单状态:

sql
CREATE TABLE Orders (
  order_id INT AUTO_INCREMENT PRIMARY KEY,  -- 订单ID(主键)
  user_id INT,                              -- 用户ID(外键,关联到用户表)
  order_status ENUM('Pending', 'Paid', 'Shipped', 'Delivered') NOT NULL,  -- 订单状态
  payment_status ENUM('Pending', 'Completed') NOT NULL,  -- 支付状态
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
  FOREIGN KEY (user_id) REFERENCES Users(user_id)  -- 外键约束,指向Users表
);
OrderItems 表(订单商品关联表)

这是一个多对多关系表,用来记录订单和商品的对应关系:

sql
CREATE TABLE OrderItems (
  order_item_id INT AUTO_INCREMENT PRIMARY KEY,  -- 订单商品记录ID
  order_id INT,                                  -- 订单ID(外键,关联到订单表)
  product_id INT,                                -- 商品ID(外键,关联到商品表)
  quantity INT NOT NULL,                         -- 商品数量
  price DECIMAL(10, 2) NOT NULL,                 -- 商品价格
  FOREIGN KEY (order_id) REFERENCES Orders(order_id),  -- 外键约束,指向Orders表
  FOREIGN KEY (product_id) REFERENCES Products(product_id)  -- 外键约束,指向Products表
);
Cart 表(购物车表)

购物车表存储用户购物车的基本信息:

sql
CREATE TABLE Carts (
  cart_id INT AUTO_INCREMENT PRIMARY KEY,  -- 购物车ID(主键)
  user_id INT,                             -- 用户ID(外键,关联到用户表)
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
  FOREIGN KEY (user_id) REFERENCES Users(user_id)  -- 外键约束,指向Users表
);
CartItems 表(购物车商品关联表)

这是另一个多对多关系表,记录购物车和商品的对应关系:

sql
CREATE TABLE CartItems (
  cart_item_id INT AUTO_INCREMENT PRIMARY KEY,  -- 购物车商品记录ID
  cart_id INT,                                  -- 购物车ID(外键,关联到购物车表)
  product_id INT,                                -- 商品ID(外键,关联到商品表)
  quantity INT NOT NULL,                         -- 商品数量
  FOREIGN KEY (cart_id) REFERENCES Carts(cart_id),  -- 外键约束,指向Carts表
  FOREIGN KEY (product_id) REFERENCES Products(product_id)  -- 外键约束,指向Products表
);

6. 总结:建模过程

  • 识别实体:通过业务需求识别系统中的核心数据实体(如用户、商品、订单等)。
  • 定义属性:为每个实体定义属性(字段),确保字段能准确描述实体的特征。
  • 确定关系:分析实体之间的关系,并根据业务需求决定关系类型(如一对多、多对多)。
  • 绘制 ER 图:用 ER 图或类图表示实体之间的关系,帮助可视化理解。
  • 设计表结构:根据 ER 图将数据模型转换为实际的数据库表,并考虑字段类型、约束、索引等。

7. 后续步骤

  • 通过 SQL 语句创建数据库表。
  • 在实践中,通过不断调整和优化数据结构,以应对业务需求的变化。

这样,通过建模,数据库的设计不仅能够清晰、有效地映射业务需求,还能保证数据的高效存储和查询。

二、NoSQL 数据库建模

NoSQL 数据库不同于传统的关系型数据库,它采用的是灵活、非结构化的数据模型,适用于高并发、低延迟和大规模分布式存储的场景。NoSQL 的数据库类型包括文档型、列族型、键值型和图数据库等。

在 NoSQL 数据库中,建模的方式与关系型数据库有很大的区别,通常更加注重性能和灵活性,避免过多的结构化设计和复杂的表连接。我们会根据不同的 NoSQL 数据库类型,采用不同的建模方法。

1. 选择 NoSQL 数据库类型

首先,我们需要根据业务需求选择合适的 NoSQL 数据库类型,不同的 NoSQL 数据库适用于不同场景:

  • 键值数据库(Key-Value Store):适用于高并发、高性能的缓存和 session 存储,如 RedisRiak
  • 文档型数据库(Document Store):适合存储半结构化数据,尤其是 JSON 格式的数据,如 MongoDBCouchDB
  • 列族型数据库(Column Family Store):适合大规模分布式数据存储,适用于时间序列数据等高吞吐量的应用,如 HBaseCassandra
  • 图数据库(Graph Database):适用于处理复杂关系数据,如 Neo4jArangoDB

2. 建模方法与实践

在 NoSQL 数据库建模时,通常遵循以下几种思路:

  1. 去规范化(Denormalization)

    • 在关系型数据库中,我们通常会采用规范化的方式来设计表结构,以减少冗余数据。然而,在 NoSQL 中,由于高性能要求和数据模型的灵活性,往往会选择去规范化,即将相关数据存储在同一文档或记录中,以避免频繁的联接查询。
    • 示例:在文档型数据库 MongoDB 中,可能会把用户信息和用户的订单信息存储在同一个文档里,而不是分开存储在不同的表中。
  2. 聚合(Aggregation)

    • 聚合指的是将相关的数据聚合到一个单独的实体中,以便在查询时能够一次性获取所有相关数据。这样做的好处是减少了查询时的多次 IO 操作。
    • 示例:例如,一个电商系统中,可以将商品的评论、评分等信息和商品本身存储在同一个文档中,而不是分开存储在不同的表里。
  3. 索引优化

    • 在 NoSQL 中,我们通常会依赖索引来优化查询。因为 NoSQL 是无模式的,字段的查询可能非常多变,所以需要根据实际查询的需求设计合适的索引。
    • 示例:在 MongoDB 中,可以为 product_namecategory 等字段创建复合索引,以加快基于这些字段的查询。
  4. 使用数据模式(Data Modeling)

    • 例如,MongoDB 是文档型数据库,使用 BSON 格式存储数据,这个过程就需要我们设计如何存储文档以及字段的数据结构。在设计时,需要注意如何平衡数据的冗余、查询效率和写入效率。

3. NoSQL 数据库建模:电商系统案例

我们以电商系统为例,来说明如何在 NoSQL 数据库中进行建模。这里我们使用 MongoDB 作为文档型数据库。

核心实体与属性

  • 用户(User):包括用户名、邮箱、密码、地址等。
  • 商品(Product):包括商品名称、描述、价格、库存等。
  • 订单(Order):包括订单 ID、用户 ID、订单状态、商品列表等。
  • 购物车(Cart):包括用户 ID、商品列表等。

4. 设计文档结构(MongoDB 示例)

用户(User)

在 MongoDB 中,用户可以存储为一个文档,包含用户的基本信息,以及嵌套的订单信息和购物车信息。

json
{
  "_id": ObjectId("someuniqueid"),
  "username": "john_doe",
  "email": "john@example.com",
  "password": "hashed_password",
  "addresses": [
    {
      "type": "home",
      "address": "123 Main St, Anytown, USA"
    }
  ],
  "orders": [
    {
      "order_id": "order123",
      "status": "Paid",
      "items": [
        {
          "product_id": "prod001",
          "quantity": 2,
          "price": 19.99
        }
      ],
      "total": 39.98,
      "created_at": "2025-01-01T00:00:00Z"
    }
  ],
  "cart": [
    {
      "product_id": "prod002",
      "quantity": 1
    }
  ]
}
商品(Product)

商品表可以存储商品的基本信息,价格、库存等:

json
{
  "_id": ObjectId("prod001"),
  "name": "Laptop",
  "description": "High-performance laptop",
  "price": 999.99,
  "stock": 100,
  "category": "Electronics",
  "tags": ["laptop", "electronics", "computer"]
}
订单(Order)

订单信息包含了与用户、商品之间的关系,订单可以嵌套商品信息,表示用户购买了哪些商品。

json
{
  "_id": ObjectId("order123"),
  "user_id": ObjectId("someuniqueid"),
  "status": "Paid",
  "items": [
    {
      "product_id": ObjectId("prod001"),
      "quantity": 2,
      "price": 19.99
    }
  ],
  "total": 39.98,
  "created_at": "2025-01-01T00:00:00Z"
}
购物车(Cart)

购物车与订单类似,也可以存储为一个文档,包含购物车内的商品信息。

json
{
  "_id": ObjectId("cart123"),
  "user_id": ObjectId("someuniqueid"),
  "items": [
    {
      "product_id": ObjectId("prod001"),
      "quantity": 1
    },
    {
      "product_id": ObjectId("prod002"),
      "quantity": 3
    }
  ]
}

5. 索引设计

在 NoSQL 中,虽然不需要像关系型数据库一样设计外键,但我们需要在查询频繁的字段上设计索引。例如,MongoDB 可以在 product_iduser_id 等字段上创建索引,以提高查询效率:

javascript
db.products.createIndex({ name: 1 });
db.orders.createIndex({ user_id: 1 });
db.carts.createIndex({ user_id: 1 });

6. 优化与扩展性

  • 水平扩展:NoSQL 数据库通常具有很好的水平扩展性,可以通过分片技术将数据分布到多个节点上。对于 MongoDB,我们可以使用分片来将数据水平扩展。
  • 去冗余与聚合:根据业务需求,将多个数据模型合并在同一个文档中,以减少查询的复杂度和 IO 消耗。

总结

  • 建模目标:在 NoSQL 数据库中,我们更注重数据模型的灵活性和高性能查询。通常采用去规范化、聚合和索引优化的方式来设计数据模型。
  • 设计重点:NoSQL 数据建模要关注高并发、高吞吐量的性能需求,同时还需要考虑数据冗余和查询效率的平衡。
  • 灵活性与扩展性:NoSQL 数据库的设计更注重系统的可扩展性和灵活性,因此我们不需要过度依赖复杂的结构化设计和连接操作。

三、结论:哪个应用更广泛?(以电商系统为例)

综合来看,关系型数据库在电商系统中的应用更广泛,特别是在电商系统的核心部分,比如用户管理、订单管理、商品管理等。主要原因包括:

  1. 数据一致性和事务处理:电商系统中的核心业务需要强一致性和高可靠性,关系型数据库提供了完整的 ACID 支持,适合复杂事务的处理。

  2. 复杂查询需求:电商系统中涉及到大量的数据关联查询,关系型数据库的 SQL 语言能够高效地处理这些复杂的查询。

  3. 规范化数据建模:电商系统中的核心数据模型通常是规范化的(如用户、订单、商品等),关系型数据库在这方面的设计非常高效。

尽管如此,NoSQL 数据库在一些场景下也有重要作用,尤其是在处理高并发、分布式数据存储和灵活的数据建模方面,如商品评价、用户行为日志、实时推荐系统等。为了满足这些场景的需求,许多电商系统会采用 混合架构,即 关系型数据库+NoSQL 数据库,两者各自发挥优势。

注意

以上结论,仅仅是基于电商系统的典型应用场景,实际应用中,选择哪种数据库,还需要根据具体业务需求、数据规模、性能要求等因素综合考虑。