You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL如何合理组织用户数据规避单表行大小限制问题

Quiz应用用户数据存储优化方案

结论先说:必须拆分多表设计,绝对不能继续沿用当前单表挂载所有数组/JSON关联数据的方案,65KB行上限是硬约束,业务跑半年到一年大概率触发故障,即使没触发上限性能也会差到没法用。

先算最直观的账:按用户连续使用5年、每天登录的场景,光登录日期就有1800+条,存成JSON字符串大概20KB;学习日程如果每天学10张闪卡,5年就是1.8万条记录,存成JSON至少500KB,早就远超InnoDB单条行65KB的上限。哪怕用TEXT/LONGTEXT类型触发InnoDB行溢出,把大字段存在额外的溢出页,每次查询用户信息都要拉取几百KB的大字段,缓存命中率、IO性能都会崩,完全没有扩展性。

具体表结构设计

核心思路是:主表只存用户本身的固定、短字段属性,所有一对多、多对多的关联数据全部分拆成独立关联表,彻底避免单条记录无限膨胀。

1. 保留users主表

只放用户基础属性,所有数组、JSON类变长关联数据全部移出:

CREATE TABLE users (
  user_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(50) NOT NULL UNIQUE,
  email VARCHAR(100) NOT NULL UNIQUE,
  password_hash VARCHAR(255) NOT NULL,
  nickname VARCHAR(50) DEFAULT NULL,
  avatar_url VARCHAR(255) DEFAULT NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  -- 其他短长度、固定属性的用户配置、基础信息放这里
  INDEX idx_username(username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2. 用户已学题集表user_learned_sets

用户和题集是多对多关系,用关联表存储,还能额外记录学习时间等扩展信息:

CREATE TABLE user_learned_sets (
  id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  user_id INT UNSIGNED NOT NULL,
  set_id INT UNSIGNED NOT NULL,
  first_learned_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_user_set (user_id, set_id), -- 避免重复记录同一题集
  FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE,
  -- 关联已有的题集主表question_sets
  FOREIGN KEY (set_id) REFERENCES question_sets(set_id) ON DELETE CASCADE,
  INDEX idx_user_id(user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

查某个用户学过的所有题集,直接按user_id查这个表就行,比解析JSON数组快几个数量级。

3. 用户好友关系表user_friends

好友是用户和用户之间的多对多关系,单独拆表:

CREATE TABLE user_friends (
  id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  user_id INT UNSIGNED NOT NULL,
  friend_user_id INT UNSIGNED NOT NULL,
  added_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 记录加好友时间
  UNIQUE KEY uk_user_friend (user_id, friend_user_id),
  FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE,
  FOREIGN KEY (friend_user_id) REFERENCES users(user_id) ON DELETE CASCADE,
  INDEX idx_user_id(user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

判断两个用户是不是好友、查某个用户的好友列表,直接走索引查询,不需要拉取整个好友数组解析。

4. 用户登录记录表user_login_logs

不要存日期数组,每次登录插一条记录,DATE类型比字符串省一半以上空间,查询统计更方便:

CREATE TABLE user_login_logs (
  id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, -- 数据量大,用BIGINT避免溢出
  user_id INT UNSIGNED NOT NULL,
  login_date DATE NOT NULL,
  login_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  -- 如果只需要记录当天是否登录,加下面的唯一键避免同一天重复插入
  UNIQUE KEY uk_user_login_date (user_id, login_date),
  INDEX idx_user_id(user_id),
  INDEX idx_login_date(login_date)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

算连续登录天数、月度登录频次这类统计,直接SQL聚合就行,不需要拉全量日期数组到应用层计算。

5. 用户学习记录表user_study_records

把原来嵌套在JSON里的每条卡片学习记录拆成独立行,彻底解决JSON无限膨胀的问题:

CREATE TABLE user_study_records (
  id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  user_id INT UNSIGNED NOT NULL,
  study_time DATETIME NOT NULL, -- 对应原JSON里的时间key
  card_id INT UNSIGNED NOT NULL, -- 对应原JSON里的卡片ID(551/552这类)
  study_type VARCHAR(20) NOT NULL, -- 对应原JSON里的type,比如Flashcards
  set_id INT UNSIGNED NOT NULL, -- 对应原JSON里的setid
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_user_study_time(user_id, study_time), -- 按时间查学习日程直接走这个索引
  INDEX idx_user_set(user_id, set_id),
  FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE,
  FOREIGN KEY (set_id) REFERENCES question_sets(set_id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

折中方案(如果不想完全拆碎学习记录)

如果90%的场景都是按天拉取用户学习日程,不需要单条卡片维度的复杂筛选,可以不用把学习记录拆到单卡片维度,按天粒度存JSON即可,单条记录最多几KB,永远碰不到65KB上限:

CREATE TABLE user_daily_study (
  id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  user_id INT UNSIGNED NOT NULL,
  study_date DATE NOT NULL,
  schedule_data JSON NOT NULL, -- 仅存当天的所有学习卡片数据
  UNIQUE KEY uk_user_date (user_id, study_date),
  INDEX idx_user_id(user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

原方案的其他隐性问题

除了行大小上限,原方案还有两个致命问题:

  • 并发更新冲突:不管是更新学习进度、加好友还是记录登录,都需要先读整行的JSON/数组,修改后整行写回,两个端同时操作很容易出现覆盖丢失数据。
  • 查询性能极差:所有筛选、统计操作都不能走索引,要么全量拉取大字段到应用层解析,要么写复杂的JSON函数查询,数据量到10万用户级别就会出现大量慢查询。

内容的提问来源于stack exchange,提问作者script ing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:15:37