任务表必须包含TINYINT类型的status字段(0=待办,1=进行中,2=已完成)和TIMESTAMP类型的updated_at字段(DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP),描述用TEXT,标签用JSON类型存储并按需添加生成列索引。
任务管理系统最核心的是能区分「待办」「进行中」「已完成」,所以 tasks 表里至少要有 status(建议用 ENUM 或 TINYINT)和 created_at/updated_at。别用 DATETIME 默认值 NOW() 做更新时间——MySQL 5.6+ 才支持 ON UPDATE CURRENT_TIMESTAMP 对 DATETIME 生效,老版本会静默失效,直接用 TIMESTAMP 更稳妥。
status 推荐用 TINYINT:0=待办,1=进行中,2=已完成;比字符串节省空间,也避免大小写/空格导致的查询不一致updated_at 必须设为 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
assignee_id(关联用户表),但别在任务表里冗余用户名——那是 JOIN 时的事
MySQL 支持外键,但简易系统里不强制启用。如果你用的是云数据库(如阿里云 RDS、腾讯云 CDB),默认可能禁用外键或不支持级联操作;就算开启,ON DELETE CASCADE 在误删用户时反而危险。更实际的做法是:建索引 + 应用层校验。
tasks.assignee_id 上建普通索引:CREATE INDEX idx_tasks_assignee ON tasks(assignee_id);
users.id 是否存在;删除用户前,先查 SELECT COUNT(*) FROM tasks WHERE assignee_id = ?
描述内容不可预估长度,VARCHAR(2000) 看似够用,但用户粘贴带格式的文本、URL、代码片段后很容易超限,报错 Data too long for column。直接上 TEXT 更省心,且现代 MySQL(8.0+)对 TEXT 的性能优化已足够好。
TEXT 不影响 WHERE 查询效率,只要不用 LIKE '%xxx%' 全模糊匹配FULLTEXT 索引:ALTER TABLE tasks ADD FULLTEXT(description);
MEDIUMTEXT 或 LONGTEXT——没意义,还可能触发某些 ORM 的类型映射异常简易系统里,优先级(高/中/低)和标签(如 #bug #feature)都建议用「枚举型字段 + 应用层解析」,而不是建关联表。否则光一个标签功能就要搭 task_tags、tags 两张表+中间表,复杂度翻倍。
priority TINYINT DEFAULT 1(1=低,2=中,3=高),查询时 ORDER BY priority DESC
tags JSON DEFAULT NULL(MySQL 5.7+),存成 ["bug", "backend"];应用层做增删查,避免多对多关联JSON_CONTAINS(tags, '"bug"'),比 JOIN 多张表快得多tags 做高频查询却不加生成列索引,会导致全表扫描。先跑通逻辑,再根据慢查询日志加索引,比一开始就堆设计更靠谱。