Skip to content

后端数据库设计 - MySQL 5.7

一、设计原则

1.1 总体原则

  • 单表+JSON动态字段方案(房源类型扩展)
  • MySQL 5.7兼容(JSON类型需特殊处理)
  • 保留现有表结构,扩展新字段
  • 统一字符集:utf8mb4
  • 统一排序规则:utf8mb4_unicode_ci

1.2 命名规范

  • 表名:小写字母+下划线(如:property_commissions
  • 字段名:小写字母+下划线(如:property_type
  • 索引:idx_字段名
  • 主键:自增INT UNSIGNED

二、核心表设计

2.1 properties表(房源表)- 扩展

扩展字段

sql
ALTER TABLE properties
ADD COLUMN property_type ENUM('residential', 'shop', 'office', 'factory', 'warehouse', 'garage', 'land', 'other') 
    DEFAULT 'residential' 
    COMMENT '房源类型:residential-住宅,shop-商铺,office-写字楼,factory-厂房,warehouse-仓库,garage-车库,land-土地,other-其他',
    
ADD COLUMN is_short_term TINYINT DEFAULT 0 
    COMMENT '是否短租 1:是 0:否',
    
ADD COLUMN rent_unit ENUM('day', 'month', 'year') 
    DEFAULT 'month' 
    COMMENT '计价单位:day-天,month-月,year-年',
    
ADD COLUMN min_rent_period INT 
    COMMENT '最短租期(天/月,根据rent_unit)',
    
ADD COLUMN extra_fields TEXT 
    COMMENT '动态字段(JSON格式,不同类型特有字段)',
    
ADD COLUMN videos TEXT 
    COMMENT '视频列表(JSON数组)',
    
ADD COLUMN commission_id INT UNSIGNED 
    COMMENT '关联委托单ID',
    
ADD COLUMN owner_remark TEXT 
    COMMENT '房东备注(前台不显示)',

ADD INDEX idx_property_type (property_type),
ADD INDEX idx_is_short_term (is_short_term),
ADD INDEX idx_commission_id (commission_id);

extra_fields字段说明

存储JSON格式的动态字段,根据property_type不同存储不同内容:

住宅(residential)

json
{
  "elevator": true,           // 是否有电梯
  "parking": 2,               // 车位数量
  "heating_type": "集中供暖", // 供暖方式
  "water_electricity": "民用" // 水电类型
}

门头房(shop)

json
{
  "street_facing": true,      // 是否临街
  "width": 8,                 // 展示面宽度(米)
  "height": 4.5,              // 层高(米)
  "suitable_business": "餐饮", // 适合业态
  "has_smoke": true,          // 是否可明火
  "transfer_fee": 50000       // 转让费
}

车库(garage)

json
{
  "parking_count": 2,         // 车位数量
  "height": 3.5,              // 层高(米)
  "independent_property": true, // 是否独立产权
  "has_electricity": true,    // 是否通电
  "security": "24小时监控"    // 安保情况
}

写字楼(office)

json
{
  "floor": 10,                // 所在楼层
  "total_floor": 28,          // 总楼层
  "height": 3.0,              // 层高(米)
  "elevator": true,           // 是否有电梯
  "elevator_count": 4,        // 电梯数量
  "parking_count": 50,        // 停车位数量
  "air_conditioning": "中央空调", // 空调类型
  "management_fee": 15.0,      // 物业费(元/㎡/月)
  "has_reception": true,       // 是否有前台
  "has_meeting_room": true     // 是否有会议室
}

厂房(factory)

json
{
  "factory_type": "标准厂房",  // 厂房类型
  "structure": "钢结构",       // 建筑结构
  "height": 8.0,              // 层高(米)
  "has_electricity": true,    // 是否通电
  "power_capacity": "500KW",  // 电力容量
  "truck_access": true,       // 是否可进大车
  "fire_system": true,        // 是否有消防系统
  "has_office": true,         // 是否有办公区
  "suitable_industry": "轻工业" // 适合行业
}

仓库(warehouse)

json
{
  "warehouse_type": "普通仓库", // 仓库类型
  "height": 6.0,              // 层高(米)
  "has_electricity": true,    // 是否通电
  "truck_access": true,       // 是否可进大车
  "loading_area": true,       // 是否有装卸区
  "fire_system": true,        // 是否有消防系统
  "is_cold_storage": false,    // 是否是冷库
  "ventilation_system": true, // 是否有通风系统
  "moisture_proof": true      // 是否防潮
}

土地(land)

json
{
  "land_area": 5000.0,        // 土地面积(㎡)
  "land_type": "工业用地",    // 土地性质
  "land_use_rights": "50年",  // 土地使用权年限
  "land_certificate": true,   // 是否有土地证
  "has_water": true,          // 是否有水
  "has_electricity": true,    // 是否通电
  "planning_permit": true,    // 是否有规划许可证
  "plot_ratio": 1.5,         // 容积率
  "suitable_purpose": "建厂" // 适合用途
}

videos字段说明

存储JSON数组格式的视频列表:

json
[
  {
    "id": 1,
    "url": "/uploads/videos/2025/11/xxx.mp4",
    "thumbnail": "/uploads/videos/2025/11/xxx_thumb.jpg",
    "duration": 120,        // 时长(秒)
    "size": 10485760,       // 大小(字节)
    "sort": 1               // 排序
  },
  {
    "id": 2,
    "url": "/uploads/videos/2025/11/yyy.mp4",
    "thumbnail": "/uploads/videos/2025/11/yyy_thumb.jpg",
    "duration": 180,
    "size": 15728640,
    "sort": 2
  }
]

2.2 property_commissions表(委托单表)- 新增

sql
CREATE TABLE property_commissions (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  commission_no VARCHAR(20) NOT NULL UNIQUE COMMENT '委托编号 如:WT202511010001',
  
  -- 委托人信息
  landlord_id INT UNSIGNED NOT NULL COMMENT '房东用户ID',
  
  -- 接单信息
  agent_id INT UNSIGNED COMMENT '接单经纪人ID',
  accept_time TIMESTAMP NULL COMMENT '接单时间',
  
  -- 房源基本信息
  property_type ENUM('residential', 'shop', 'office', 'factory', 'warehouse', 'garage', 'land', 'other') NOT NULL COMMENT '房源类型',
  community_id INT UNSIGNED NOT NULL COMMENT '小区ID',
  title VARCHAR(100) NOT NULL COMMENT '标题',
  type ENUM('sale', 'rent') NOT NULL COMMENT '交易类型',
  
  -- 价格面积
  price DECIMAL(10,2) COMMENT '期望价格',
  price_min DECIMAL(10,2) COMMENT '最低价格',
  price_max DECIMAL(10,2) COMMENT '最高价格',
  area DECIMAL(6,2) COMMENT '面积',
  
  -- 户型
  room TINYINT COMMENT '室',
  hall TINYINT COMMENT '厅',
  toilet TINYINT COMMENT '卫',
  floor TINYINT COMMENT '楼层',
  total_floor TINYINT COMMENT '总楼层',
  
  -- 装修朝向
  orientation VARCHAR(20) COMMENT '朝向',
  decoration VARCHAR(20) COMMENT '装修情况',
  
  -- 短租信息
  is_short_term TINYINT DEFAULT 0 COMMENT '是否短租',
  rent_unit ENUM('day', 'month') COMMENT '计价单位',
  min_rent_period INT COMMENT '最短租期',
  
  -- 媒体资料
  images TEXT COMMENT '房东上传的图片(JSON数组)',
  description TEXT COMMENT '房源描述',
  
  -- 动态字段
  extra_fields TEXT COMMENT '动态字段(JSON)',
  
  -- 状态管理
  status ENUM('pending', 'accepted', 'published', 'cancelled') DEFAULT 'pending' 
    COMMENT '状态:pending-待接单,accepted-已接单,published-已发布,cancelled-已取消',
  
  -- 发布信息
  publish_time TIMESTAMP NULL COMMENT '发布为房源的时间',
  property_id INT UNSIGNED COMMENT '发布后的房源ID',
  
  -- 取消信息
  cancel_reason VARCHAR(255) COMMENT '取消原因',
  cancel_time TIMESTAMP NULL COMMENT '取消时间',
  
  -- 时间戳
  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  
  -- 索引
  INDEX idx_landlord(landlord_id),
  INDEX idx_agent(agent_id),
  INDEX idx_status(status),
  INDEX idx_property_type(property_type),
  INDEX idx_create_time(create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房源委托单表';

commission_no生成规则

格式:WT + YYYYMMDD + 4位序号
示例:WT202511010001

2.3 business_districts表(商圈表)- 新增

sql
CREATE TABLE business_districts (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL COMMENT '商圈名称',
  
  -- 地理位置
  lat DECIMAL(10,7) NOT NULL COMMENT '中心纬度',
  lng DECIMAL(10,7) NOT NULL COMMENT '中心经度',
  address VARCHAR(255) COMMENT '地址描述',
  
  -- 数据来源
  source ENUM('tencent_map', 'manual') DEFAULT 'manual' 
    COMMENT '来源:tencent_map-腾讯地图,manual-手动录入',
  
  tencent_poi_id VARCHAR(100) COMMENT '腾讯地图POI ID',
  
  -- 统计数据
  property_count INT DEFAULT 0 COMMENT '关联房源数量(冗余字段)',
  
  -- 状态
  status TINYINT DEFAULT 1 COMMENT '状态 1:启用 0:禁用',
  
  -- 时间戳
  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  
  -- 索引
  INDEX idx_name(name),
  INDEX idx_source(source),
  INDEX idx_status(status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商圈表';

初始数据示例

sql
INSERT INTO business_districts (name, address, lat, lng, source) VALUES
('新都心', '青岛市市北区新都心商圈', 36.1081, 120.4037, 'manual'),
('台东', '青岛市市北区台东商圈', 36.0858, 120.3964, 'manual'),
('浮山后', '青岛市市北区浮山后商圈', 36.1094, 120.4446, 'manual'),
('CBD', '青岛市市北区中央商务区', 36.0686, 120.3826, 'manual');

2.4 property_districts表(房源商圈关联表)- 新增

sql
CREATE TABLE property_districts (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  property_id INT UNSIGNED NOT NULL COMMENT '房源ID',
  district_id INT UNSIGNED NOT NULL COMMENT '商圈ID',
  
  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  
  -- 索引
  INDEX idx_property(property_id),
  INDEX idx_district(district_id),
  UNIQUE KEY uk_property_district(property_id, district_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房源商圈关联表';

说明:支持一个房源关联多个商圈

2.5 contracts表(电子合同表)- 新增

sql
CREATE TABLE contracts (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  contract_no VARCHAR(30) NOT NULL UNIQUE COMMENT '合同编号 如:HT202511010001',
  
  -- 关联信息
  property_id INT UNSIGNED NOT NULL COMMENT '房源ID',
  
  -- 签署三方
  landlord_id INT UNSIGNED NOT NULL COMMENT '房东用户ID',
  tenant_id INT UNSIGNED NOT NULL COMMENT '租客/买家用户ID',
  agent_id INT UNSIGNED NOT NULL COMMENT '经纪人用户ID',
  
  -- 合同类型
  contract_type ENUM('rent', 'sale') NOT NULL COMMENT '合同类型:rent-租房,sale-售房',
  template_id INT UNSIGNED COMMENT '合同模板ID',
  
  -- e签宝相关
  esign_flow_id VARCHAR(100) COMMENT 'e签宝流程ID',
  esign_file_id VARCHAR(100) COMMENT 'e签宝文件ID',
  
  -- 签署状态
  landlord_signed TINYINT DEFAULT 0 COMMENT '房东是否已签署 1:是 0:否',
  tenant_signed TINYINT DEFAULT 0 COMMENT '租客是否已签署 1:是 0:否',
  agent_signed TINYINT DEFAULT 0 COMMENT '经纪人是否已签署 1:是 0:否',
  
  -- 签署时间
  landlord_sign_time TIMESTAMP NULL COMMENT '房东签署时间',
  tenant_sign_time TIMESTAMP NULL COMMENT '租客签署时间',
  agent_sign_time TIMESTAMP NULL COMMENT '经纪人签署时间',
  
  -- 合同状态
  status ENUM('draft', 'signing', 'completed', 'cancelled') DEFAULT 'draft' 
    COMMENT '状态:draft-草稿,signing-签署中,completed-已完成,cancelled-已取消',
  
  -- 合同文件
  contract_url VARCHAR(255) COMMENT '已签署合同PDF地址',
  contract_content TEXT COMMENT '合同内容(填充变量后)',
  
  -- 时间戳
  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  complete_time TIMESTAMP NULL COMMENT '完成时间',
  
  -- 索引
  INDEX idx_property(property_id),
  INDEX idx_landlord(landlord_id),
  INDEX idx_tenant(tenant_id),
  INDEX idx_agent(agent_id),
  INDEX idx_status(status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='电子合同表';

2.6 contract_templates表(合同模板表)- 新增

sql
CREATE TABLE contract_templates (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL COMMENT '模板名称',
  type ENUM('rent', 'sale') NOT NULL COMMENT '合同类型',
  
  -- 模板内容
  content TEXT NOT NULL COMMENT '模板内容(支持变量占位符)',
  
  -- e签宝模板
  esign_template_id VARCHAR(100) COMMENT 'e签宝模板ID',
  
  -- 状态
  status TINYINT DEFAULT 1 COMMENT '状态 1:启用 0:禁用',
  is_default TINYINT DEFAULT 0 COMMENT '是否默认模板 1:是 0:否',
  
  -- 时间戳
  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  
  -- 索引
  INDEX idx_type(type),
  INDEX idx_status(status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同模板表';

模板变量说明

支持的变量:
{{landlord_name}}      - 房东姓名
{{landlord_phone}}     - 房东电话
{{landlord_id_card}}   - 房东身份证
{{tenant_name}}        - 租客姓名
{{tenant_phone}}       - 租客电话
{{tenant_id_card}}     - 租客身份证
{{agent_name}}         - 经纪人姓名
{{agent_phone}}        - 经纪人电话
{{property_address}}   - 房源地址
{{property_area}}      - 房源面积
{{property_type}}      - 房源类型
{{rent_price}}         - 租金/售价
{{rent_period}}        - 租期
{{start_date}}         - 开始日期
{{end_date}}           - 结束日期
{{sign_date}}          - 签署日期

2.7 system_configs表(系统配置表)- 新增

sql
CREATE TABLE system_configs (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  config_key VARCHAR(50) NOT NULL UNIQUE COMMENT '配置键',
  config_value TEXT NOT NULL COMMENT '配置值',
  description VARCHAR(255) COMMENT '配置说明',
  
  update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统配置表';

初始配置数据

sql
INSERT INTO system_configs (config_key, config_value, description) VALUES
('video_max_count', '10', '每个房源最多视频数量'),
('video_max_size', '52428800', '单个视频最大大小(字节) 50MB'),
('video_max_duration', '1800', '视频最长时长(秒) 30分钟'),
('image_max_count', '9', '每个房源最多图片数量'),
('image_max_size', '5242880', '单个图片最大大小(字节) 5MB'),
('commission_auto_cancel_hours', '72', '委托单无人接单自动取消时间(小时)'),
('esign_app_id', '', 'e签宝App ID'),
('esign_secret', '', 'e签宝Secret'),
('esign_api_url', 'https://smlopenapi.esign.cn', 'e签宝API地址'),
('tencent_map_key', 'PVZBZ-DB46Z-WFEXI-ZCKQA-HZBWS-BLBF2', '腾讯地图密钥');

2.8 communities表(小区表)- 扩展

sql
ALTER TABLE communities
ADD COLUMN lat DECIMAL(10,7) COMMENT '纬度',
ADD COLUMN lng DECIMAL(10,7) COMMENT '经度',
ADD COLUMN build_year VARCHAR(10) COMMENT '建筑年代',
ADD COLUMN property_fee VARCHAR(50) COMMENT '物业费',
ADD COLUMN facilities TEXT COMMENT '周边配套(JSON格式)',
ADD COLUMN tencent_poi_id VARCHAR(100) COMMENT '腾讯地图POI ID',

ADD INDEX idx_lat_lng(lat, lng);

facilities字段说明

json
{
  "subway": [              // 地铁站
    {"name": "3号线五四广场站", "distance": 500}
  ],
  "bus": [                 // 公交站
    {"name": "市政府站", "distance": 200}
  ],
  "school": [              // 学校
    {"name": "青岛实验小学", "distance": 800}
  ],
  "hospital": [            // 医院
    {"name": "市北区人民医院", "distance": 1000}
  ],
  "shopping": [            // 商场
    {"name": "万达广场", "distance": 600}
  ],
  "bank": [                // 银行
    {"name": "中国银行", "distance": 300}
  ]
}

2.9 users表(用户表)- 扩展

sql
ALTER TABLE users
ADD COLUMN is_landlord TINYINT DEFAULT 0 COMMENT '是否房东身份 1:是 0:否',
ADD COLUMN esign_account_id VARCHAR(100) COMMENT 'e签宝个人账号ID',
ADD COLUMN id_card VARCHAR(18) COMMENT '身份证号(用于电子签约)',
ADD COLUMN real_name VARCHAR(50) COMMENT '真实姓名(用于电子签约)';

说明

  • is_landlord:用户发布过委托后自动设置为1
  • esign_account_id:第一次签署合同时创建e签宝账号

2.10 crawler_logs表(爬虫日志表)- 新增

sql
CREATE TABLE crawler_logs (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  user_id INT UNSIGNED NOT NULL COMMENT '操作用户ID',
  
  -- 爬取信息
  source_url VARCHAR(500) NOT NULL COMMENT '源URL',
  source_type ENUM('beike', 'anjuke') NOT NULL COMMENT '来源:beike-贝壳,anjuke-安居客',
  
  -- 结果
  status ENUM('success', 'failed') NOT NULL COMMENT '状态:success-成功,failed-失败',
  error_msg TEXT COMMENT '错误信息',
  
  -- 数据
  crawled_data TEXT COMMENT '爬取到的数据(JSON)',
  
  -- 时间戳
  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  
  -- 索引
  INDEX idx_user(user_id),
  INDEX idx_status(status),
  INDEX idx_create_time(create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='爬虫日志表';

三、MySQL 5.7兼容处理

3.1 JSON字段处理

MySQL 5.7虽然支持JSON类型,但为了更好的兼容性,建议使用TEXT类型:

sql
-- 不使用JSON类型
extra_fields JSON

-- 使用TEXT类型
extra_fields TEXT

应用层处理:

php
// 写入
$property->extra_fields = json_encode($extraData);

// 读取
$extraData = json_decode($property->extra_fields, true);

3.2 TIMESTAMP默认值

MySQL 5.7对TIMESTAMP的默认值有限制:

sql
-- 正确写法
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

3.3 字符集设置

统一使用utf8mb4:

sql
CREATE TABLE xxx (
  ...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

四、数据库迁移SQL

完整的迁移SQL文件将单独生成在: database/migrations/20251103_upgrade_to_new_version.sql

包含:

  1. 表结构修改(ALTER TABLE)
  2. 新表创建(CREATE TABLE)
  3. 初始数据插入(INSERT)
  4. 索引优化

五、索引优化建议

5.1 查询频繁字段

  • properties表:property_type、is_short_term、status
  • property_commissions表:status、landlord_id、agent_id
  • business_districts表:name、status
  • contracts表:status、property_id

5.2 联合索引

sql
-- 房源筛选常用组合
ALTER TABLE properties ADD INDEX idx_type_status(type, status);
ALTER TABLE properties ADD INDEX idx_property_type_status(property_type, status);

-- 委托单筛选
ALTER TABLE property_commissions ADD INDEX idx_status_create(status, create_time);

六、数据库维护建议

6.1 定期清理

  • crawler_logs表:保留3个月数据
  • email_codes表:定期清理过期验证码

6.2 数据备份

  • 每日增量备份
  • 每周全量备份
  • 重要操作前手动备份

6.3 性能监控

  • 慢查询日志
  • 索引使用率
  • 表大小监控

文档版本:v1.0
更新日期:2025年11月3日

最后更新于:

基于 MIT 许可发布