后端数据库设计 - 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位序号
示例:WT2025110100012.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:用户发布过委托后自动设置为1esign_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_TIMESTAMP3.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
包含:
- 表结构修改(ALTER TABLE)
- 新表创建(CREATE TABLE)
- 初始数据插入(INSERT)
- 索引优化
五、索引优化建议
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日