购物车表必须加联合唯一索引uk_user_product(user_id, sku_id),并立即引入sku_id字段;quantity用TINYINT UNSIGNED足够;生产环境不建议加外键。

购物车表要不要加唯一索引?
不加唯一索引大概率会出重复数据,尤其用户并发添加同一商品时。user_id 和 product_id 必须联合唯一,否则同个用户可能存多条相同商品记录,后续加减数量、清空逻辑全乱套。
- 唯一约束必须是
UNIQUE KEY <code>uk_user_product(user_id,product_id),不能只对product_id单独建唯一索引 - 如果用
INSERT ... ON DUPLICATE KEY UPDATE更新数量,依赖的就是这个联合唯一索引触发冲突 - 没加的话,
SELECT COUNT(*)查购物车总项数会虚高,前端显示“3件商品”实际只有2种,体验错乱
quantity 字段该用 TINYINT 还是 INT?
用 TINYINT UNSIGNED 足够,别盲目上 INT。
- 普通用户单次购物车不太可能加超过 127 件同款商品(
TINYINT上限),超量属于异常行为,应由业务层拦截而非靠字段兜底 -
TINYINT占 1 字节,INT占 4 字节,百万级购物车记录能省下近 3MB 存储+对应内存和索引开销 - 如果真要支持“批发场景”,改用
SMALLINT UNSIGNED(上限 65535)更合理,而不是一步跳到INT
外键要不要关联 users 和 products 表?
开发环境可以加,生产环境建议去掉。
- 加外键会让
DELETE FROM products WHERE id = ?变慢,尤其当购物车数据量大时,InnoDB 需扫描所有关联购物车行做约束检查 - 更麻烦的是:商品下架时,你通常不想删
products记录(要留历史订单溯源),而是设status = 'offline',此时外键反而成了干扰项 - 真正需要的是应用层保证写入的
user_id和product_id存在,比如插入前查一次缓存或走轻量校验接口
要不要单独存 sku_id?
要,而且得立刻加,别等“后面再扩展”。
- 商品有规格(如颜色/尺码)时,
product_id不足以区分不同 SKU;只存product_id+quantity,会导致“用户选了黑色 M 码,结账时变成黑色 L 码”这类问题 - 字段名直接叫
sku_id,类型跟products.id一致(通常是BIGINT),并建立索引:KEY <code>idx_sku_id(sku_id) - 联合唯一索引也要同步改成 (
user_id,sku_id),否则同用户不同规格的同款商品会互相覆盖
字段设计容易卡在“先做最小可用”还是“一步到位”,但购物车这种强状态、多端读写、且直接影响下单准确性的表,一开始就把 sku_id、联合唯一、合理数值类型定死,后面少掉三次坑。


















