t_ticket主表必须包含id、customer_id、operator_id、title、content、status、priority、created_at、updated_at、status_updated_at字段,且需合理设置类型、索引与语义分离。

工单主表 t_ticket 必须包含哪些字段
客服系统里工单是核心实体,t_ticket 不能只存标题和内容。漏掉关键字段会导致后续无法过滤、统计或对接客服SaaS接口。
-
id:用BIGINT UNSIGNED AUTO_INCREMENT,别用INT—— 高并发客服场景下月增10万单,INT2年就溢出 -
status:用TINYINT存状态码(如 1=新建, 2=处理中, 3=已解决, 4=已关闭),别用VARCHAR存“已解决”——排序、索引、JOIN 都会变慢 -
priority:同理用TINYINT(1=低, 2=中, 3=高, 4=紧急),避免模糊查询 like '%紧急%' - 必须有
created_at和updated_at,且都设为DATETIME(3)(毫秒级),客服SLA统计依赖精确到秒的更新时间 - 别忘了
customer_id(关联客户表)和operator_id(当前处理人),这两个是高频 JOIN 字段,记得加索引
工单流转记录为什么不能合并在主表里
把每次分配、转交、升级的操作都写进 t_ticket 的 last_operator_id 或 history 字段,短期省事,长期必踩坑。
- 历史不可追溯:谁在什么时间把工单转给了谁?主表只留最新值,审计、复盘时抓瞎
- 触发器或应用层拼接 JSON 到
history字段,会导致该字段越来越大,SELECT *拖慢所有查询 - 正确做法是建独立表
t_ticket_flow,字段至少含:ticket_id、from_operator_id、to_operator_id、action(如 'assign'/'transfer'/'escalate')、created_at -
t_ticket_flow上建联合索引(ticket_id, created_at),查某工单全流程只要WHERE ticket_id = ? ORDER BY created_at
status 字段变更时要不要自动更新 updated_at
要,但不能靠 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 自动机制。
开发语言:java,支持数据库:Mysql 5,系统架构:J2EE,操作系统:linux/Windows1. 引言 32. 系统的结构 32.1 系统概述 33. 功能模块设计说明 43.1 商品管理 43.1.1 添加商品功能模块 53.1.2 商品列表功能模块 83.1.3 商品关联功能模块 93.
-
ON UPDATE CURRENT_TIMESTAMP在任何字段更新时都会触发,而客服系统常批量更新description或attachment_url,不该因此污染updated_at—— 它应仅代表「业务状态变化」的时间点 - 应用层在调用
UPDATE t_ticket SET status = ?, updated_at = NOW(3) WHERE id = ?时显式赋值,更可控 - 如果用 ORM(如 Laravel Eloquent 或 Django ORM),确保状态变更逻辑走专用方法,而不是通用
save() - 额外建议:加一个
status_updated_at字段,专用于记录状态变更时间,和通用updated_at分离,避免语义混淆
附件、消息、评论该不该和工单主表放一起
绝对不要。常见错误是把图片 base64、聊天记录 JSON 全塞进 t_ticket 的 attachments 或 messages 字段。
-
TEXT或MEDIUMTEXT字段膨胀后,主表SELECT变慢,即使你只查id和title,MySQL 仍需读取整行(除非用ROW_FORMAT=COMPRESSED+BLOB外存,但太重) - 正确拆分:建
t_ticket_attachment(字段:ticket_id, file_name, file_size, url, uploaded_at)、t_ticket_message(ticket_id, sender_type, sender_id, content, sent_at) - 附件 URL 建议存相对路径(如
/uploads/ticket_12345/abc.jpg),由 Nginx 或 CDN 直接服务,别让 MySQL 承担文件传输 - 消息表必须加索引
(ticket_id, sent_at),客服坐席翻页加载历史消息时,LIMIT 20 OFFSET 100才不会全表扫
-- 示例:工单主表精简结构(不含冗余字段) CREATE TABLE `t_ticket` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `customer_id` BIGINT UNSIGNED NOT NULL, `operator_id` BIGINT UNSIGNED DEFAULT NULL, `title` VARCHAR(200) NOT NULL, `content` TEXT NOT NULL, `status` TINYINT NOT NULL DEFAULT 1, `priority` TINYINT NOT NULL DEFAULT 2, `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `updated_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), `status_updated_at` DATETIME(3) NULL, PRIMARY KEY (`id`), KEY `idx_customer_status` (`customer_id`, `status`), KEY `idx_status_priority` (`status`, `priority`), KEY `idx_operator_status` (`operator_id`, `status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
实际跑起来才发现,最麻烦的不是字段怎么设,而是「状态机」怎么落地——比如“已解决”后是否允许回退到“处理中”,这种业务规则得在应用层硬校验,数据库只管存,不替你做决策。









