mysql如何设计公告系统数据库_mysql项目案例

来源:这里教程网 时间:2026-02-28 20:49:57 作者:

公告表必须包含状态字段和发布时间精度控制

公告不是一发就完事,需要支持草稿、已发布、已过期、已撤回等生命周期管理。直接用

status TINYINT
(0=草稿,1=发布,2=过期,3=撤回)比布尔值更可持续;发布时间必须用
publish_time DATETIME
而非
created_at
,因为创建时间和实际对外展示时间常不一致。

避免用
is_published BOOLEAN
:后期加“定时发布”“撤回重发”时会卡死
publish_time
建议设默认值
CURRENT_TIMESTAMP
,但允许为空,方便存草稿时不填
如果需毫秒级定时(比如精确到秒内推送),用
publish_time DECIMAL(13,3)
存 Unix 时间戳(PHP/Java 易处理),MySQL 8.0+ 也可用
TIMESTAMP(3)

分类与标签应分离,优先用多对多关联而非 JSON 字段

公告常需按“系统通知|活动公告|维护提醒”分类,还可能打“紧急|重要|普通”标签。别把分类 ID 和标签数组塞进一个

category_json TEXT
字段——查起来慢,没法索引,改起来容易错。

建独立
notice_categories
表,主键
id
+
name
+
code
(如
'maintenance'
建关联表
notice_category_map
:字段为
notice_id
category_id
is_primary TINYINT
(标出主分类)
标签同理,用
notice_tags
+
notice_tag_map
;除非标签数固定且极少(≤3),否则别用逗号分隔字符串

内容存储要区分富文本与纯文本,且必须限制长度

前端编辑器输出的 HTML 内容动辄上万字符,但 MySQL 的

TEXT
类型在排序、WHERE 查询时性能差;而纯文本摘要又不能丢——搜索、列表预览、微信服务号推送都靠它。

必存两个字段:
content_html MEDIUMTEXT
(完整 HTML)、
content_plain VARCHAR(2000)
(自动提取的纯文本摘要)
禁止用
LONGTEXT
:除非你确定单条公告超 4GB,否则浪费空间且影响 InnoDB 缓冲池效率
插入前强制截断
content_plain
到 2000 字符(用
SUBSTRING_INDEX(SUBSTRING(content_html, 1, 5000), '', 1)
等逻辑预处理),防止超长报错

读多写少场景下,务必加覆盖索引避免回表

公告列表页查的是“状态=1 且 publish_time ≤ NOW()”,返回 id/title/publish_time/status —— 如果只在

status
publish_time
上分别建索引,MySQL 仍要回表取 title,QPS 高时 I/O 成瓶颈。

建联合索引:
INDEX idx_status_time (status, publish_time)
再加覆盖索引:
INDEX idx_status_time_cover (status, publish_time, id, title)
,让查询完全走索引不回表
注意:
status
必须放联合索引最左,因为 WHERE 中是等值过滤;
publish_time
是范围查询,放其后
真实项目里最容易被跳过的,是草稿状态下的
publish_time
允许为空 + 联合索引中
status
的低基数导致优化器误选索引——上线前一定用
EXPLAIN
验证公告列表 SQL 是否命中覆盖索引。

相关推荐