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

6次阅读

公告表需设status字段(0=草稿,1=发布,2=过期,3=撤回)和publish_time datetime(支持空值及毫秒级可选),分类与标签须分表关联,内容存content_html与content_plain双字段,列表查询须建status+publish_time覆盖索引。

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

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

公告不是一发就完事,需要支持草稿、已发布、已过期、已撤回等生命周期管理。直接用 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_idcategory_idis_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 —— 如果只在 statuspublish_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 是否命中覆盖索引。

text=ZqhQzanResources