当前位置:首页 > 问答 > 正文

数据库设计 实战训练 挑战你的数据库设计能力:30道实用型数据库设计题

🔥 数据库设计实战:30道烧脑题挑战你的SQL大脑!

大家好!我是老王,一个在数据库领域摸爬滚打了10年的老码农,今天想和大家分享一些超实用的数据库设计实战题目,保证让你既爱又恨!💪

🚀 为什么数据库设计如此重要?

记得去年我们公司新来的小张吗?他设计了一个"完美"的用户系统——把所有用户信息都塞进一张表里,结果双十一那天系统直接崩了!😱 这就是为什么我们要好好学数据库设计!

🧠 热身题:先来点简单的

  1. 电商基础版:设计一个简单的电商数据库,包含用户、商品和订单
-- 用户表
CREATE TABLE users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 商品表
CREATE TABLE products (
    product_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    stock INT DEFAULT 0
);
-- 订单表
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    user_id INT REFERENCES users(user_id),
    order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    total_amount DECIMAL(10,2)
);
  1. 朋友圈设计:如何存储用户发帖和点赞关系?
-- 帖子表
CREATE TABLE posts (
    post_id INT PRIMARY KEY,
    user_id INT REFERENCES users(user_id),
    content TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 点赞表(多对多关系)
CREATE TABLE likes (
    like_id INT PRIMARY KEY,
    user_id INT REFERENCES users(user_id),
    post_id INT REFERENCES posts(post_id),
    UNIQUE(user_id, post_id)  -- 防止重复点赞
);

💼 中级挑战:业务场景更复杂了!

  1. 酒店预订系统:房间类型、预订日期冲突怎么处理?
-- 房间类型表
CREATE TABLE room_types (
    type_id INT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    price_per_night DECIMAL(10,2) NOT NULL,
    capacity INT NOT NULL
);
-- 房间表
CREATE TABLE rooms (
    room_id INT PRIMARY KEY,
    type_id INT REFERENCES room_types(type_id),
    room_number VARCHAR(10) UNIQUE NOT NULL
);
-- 预订表(关键是如何处理日期冲突)
CREATE TABLE reservations (
    reservation_id INT PRIMARY KEY,
    room_id INT REFERENCES rooms(room_id),
    guest_id INT REFERENCES users(user_id),
    check_in DATE NOT NULL,
    check_out DATE NOT NULL,
    status VARCHAR(20) DEFAULT 'confirmed',
    CONSTRAINT no_overlap EXCLUDE USING gist (
        room_id WITH =,
        daterange(check_in, check_out) WITH &&
    )
);
  1. 课程管理系统:学生选课、教师授课、课程排课
-- 学生表
CREATE TABLE students (
    student_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    enrollment_date DATE NOT NULL
);
-- 教师表
CREATE TABLE teachers (
    teacher_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    department VARCHAR(50)
);
-- 课程表
CREATE TABLE courses (
    course_id INT PRIMARY KEY,VARCHAR(100) NOT NULL,
    credits INT NOT NULL
);
-- 教学班表(考虑时间地点)
CREATE TABLE classes (
    class_id INT PRIMARY KEY,
    course_id INT REFERENCES courses(course_id),
    teacher_id INT REFERENCES teachers(teacher_id),
    semester VARCHAR(20) NOT NULL,
    schedule JSONB,  -- 存储复杂的时间安排
    classroom VARCHAR(20)
);
-- 选课表
CREATE TABLE enrollments (
    enrollment_id INT PRIMARY KEY,
    student_id INT REFERENCES students(student_id),
    class_id INT REFERENCES classes(class_id),
    enrollment_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    grade DECIMAL(3,1),
    UNIQUE(student_id, class_id)
);

🧩 高级难题:这些设计会让你掉头发!

  1. 多租户SaaS系统:如何设计让不同客户数据隔离但共享代码?
-- 租户表
CREATE TABLE tenants (
    tenant_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    subdomain VARCHAR(50) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 用户表(带租户ID)
CREATE TABLE tenant_users (
    user_id INT PRIMARY KEY,
    tenant_id INT REFERENCES tenants(tenant_id),
    email VARCHAR(100) NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    UNIQUE(tenant_id, email)
);
-- 所有业务表都要加上tenant_id
CREATE TABLE tenant_products (
    product_id INT PRIMARY KEY,
    tenant_id INT REFERENCES tenants(tenant_id),
    name VARCHAR(100) NOT NULL,
    -- 其他字段...
);
  1. 版本控制系统:如何存储文件的历史版本和差异?
-- 仓库表
CREATE TABLE repositories (
    repo_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 文件表
CREATE TABLE files (
    file_id INT PRIMARY KEY,
    repo_id INT REFERENCES repositories(repo_id),
    path VARCHAR(255) NOT NULL,
    is_directory BOOLEAN DEFAULT FALSE,
    UNIQUE(repo_id, path)
);
-- 文件版本表
CREATE TABLE file_versions (
    version_id INT PRIMARY KEY,
    file_id INT REFERENCES files(file_id),
    commit_id INT NOT NULL,  -- 引用提交记录
    content BYTEA,
    size INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 差异表(存储版本间差异)
CREATE TABLE diffs (
    diff_id INT PRIMARY KEY,
    from_version INT REFERENCES file_versions(version_id),
    to_version INT REFERENCES file_versions(version_id),
    patch TEXT NOT NULL
);

🏆 终极挑战:这些题目能测出你的真实水平!

  1. 实时股票交易系统:高频写入、低延迟查询如何优化?
-- 股票基本信息
CREATE TABLE stocks (
    stock_id INT PRIMARY KEY,
    symbol VARCHAR(10) UNIQUE NOT NULL,
    company_name VARCHAR(100) NOT NULL
);
-- 分时行情表(考虑分区)
CREATE TABLE stock_quotes (
    quote_id BIGSERIAL PRIMARY KEY,
    stock_id INT REFERENCES stocks(stock_id),
    price DECIMAL(10,2) NOT NULL,
    volume INT NOT NULL,
    quote_time TIMESTAMPTZ NOT NULL
) PARTITION BY RANGE (quote_time);
-- 创建按天的分区
CREATE TABLE stock_quotes_202501 PARTITION OF stock_quotes
    FOR VALUES FROM ('2025-01-01') TO ('2025-01-31');
-- 更多分区...
-- 订单表(考虑索引优化)
CREATE TABLE orders (
    order_id BIGSERIAL PRIMARY KEY,
    user_id INT NOT NULL,
    stock_id INT REFERENCES stocks(stock_id),
    order_type VARCHAR(4) CHECK (order_type IN ('BUY', 'SELL')),
    price DECIMAL(10,2) NOT NULL,
    quantity INT NOT NULL,
    status VARCHAR(20) DEFAULT 'PENDING',
    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
-- 为高频查询创建索引
CREATE INDEX idx_orders_stock_status ON orders(stock_id, status);
CREATE INDEX idx_quotes_stock_time ON stock_quotes(stock_id, quote_time);
  1. 社交网络图谱:如何高效存储和查询好友关系?
-- 用户表
CREATE TABLE social_users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    -- 其他个人信息...
);
-- 好友关系表(使用图数据库可能更合适)
CREATE TABLE friendships (
    user1_id INT REFERENCES social_users(user_id),
    user2_id INT REFERENCES social_users(user_id),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    status VARCHAR(20) DEFAULT 'accepted',
    PRIMARY KEY (user1_id, user2_id),
    CHECK (user1_id < user2_id)  -- 避免重复关系
);
-- 为了高效查询好友的好友(二度人脉)
CREATE MATERIALIZED VIEW friend_of_friend AS
SELECT f1.user1_id AS user_id, 
       f2.user2_id AS friend_of_friend_id,
       COUNT(*) OVER (PARTITION BY f1.user1_id, f2.user2_id) AS common_friends
FROM friendships f1
JOIN friendships f2 ON f1.user2_id = f2.user1_id
WHERE f2.user2_id != f1.user1_id;
-- 定期刷新物化视图
REFRESH MATERIALIZED VIEW friend_of_friend;

🎯 更多实用题目(简要思路)

  1. 物流跟踪系统:包裹状态流转、路线规划

    数据库设计 实战训练 挑战你的数据库设计能力:30道实用型数据库设计题

    • 设计状态机表记录包裹每个状态变更
    • 地理空间数据存储运输路线
  2. 医疗信息系统:患者病历、检查报告、药品处方

    • 严格的权限控制和数据加密
    • 复杂的关联关系和审计日志
  3. 物联网平台:海量设备数据存储和查询

    • 时序数据库设计
    • 数据降采样和归档策略
  4. 管理多种语言版本

    • 灵活的翻译存储方案
    • 回退语言机制

...(限于篇幅,其他题目不再展开)

数据库设计 实战训练 挑战你的数据库设计能力:30道实用型数据库设计题

💡 数据库设计黄金法则

  1. 规范化是基础:但不要过度,有时反规范化是必要的
  2. 索引是双刃剑:加速查询但降低写入速度
  3. 考虑增长:今天100条记录,明天可能是1亿条
  4. 安全第一:SQL注入、数据泄露都是致命的
  5. 文档!文档!文档!:三个月后你会感谢自己写了注释

🤔 思考题

最后留几个开放性问题给大家思考:

  • 如何设计一个支持"撤销"操作的数据模型?
  • 分布式数据库如何保证数据一致性?
  • 时间序列数据的最佳存储策略是什么?

涵盖了从基础到高级的各种数据库设计场景,好的数据库设计不是一蹴而就的,需要不断实践和优化,下次当你设计表结构时,不妨先问问自己:

  • 我的设计能应对业务增长吗?
  • 最常见的查询会高效吗?
  • 数据一致性能保证吗?

希望这些实战题目能帮你成为数据库设计高手!如果有特别感兴趣的题目想深入了解,欢迎留言讨论哦!🎉 参考2025年8月最新数据库设计实践)

发表评论