MySQL 中为产品添加灵活的自定义属性(如 color/size)


方案 1:EAV 模型(最灵活但较复杂)

适合需要无限扩展自定义属性的场景

-- 产品表
CREATE TABLE products (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100),
  price DECIMAL(10,2)
);

-- 属性名表
CREATE TABLE attributes (
  id INT PRIMARY KEY AUTO_INCREMENT,
  attr_name VARCHAR(50) UNIQUE -- color/size 等
);

-- 属性值表
CREATE TABLE product_attributes (
  product_id INT,
  attribute_id INT,
  value VARCHAR(255),
  PRIMARY KEY (product_id, attribute_id),
  FOREIGN KEY (product_id) REFERENCES products(id),
  FOREIGN KEY (attribute_id) REFERENCES attributes(id)
);

优点

  • 无限扩展新属性
  • 属性可复用(如多个产品共用 color 属性)
  • 便于统一管理属性

缺点

  • 查询复杂(需要多次 JOIN)
  • 难以对特定属性建立索引
  • 值只能是字符串类型
  • 数据验证需在应用层实现

方案 2:JSON 字段(MySQL 5.7+ 推荐)

适合属性结构灵活变化的场景

CREATE TABLE products (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100),
  price DECIMAL(10,2),
  attributes JSON NOT NULL
);

-- 插入示例
INSERT INTO products 
VALUES (1, 'T-Shirt', 29.99, 
  '{"color": "red", "size": "XL", "material": "cotton"}');

查询示例

-- 查询特定颜色
SELECT * FROM products
WHERE JSON_EXTRACT(attributes, '$.color') = 'red';

-- 查询特定尺寸
SELECT * FROM products
WHERE attributes->"$.size" = 'XL';

-- 创建虚拟列并建立索引(优化查询)
ALTER TABLE products
ADD COLUMN color VARCHAR(30) 
GENERATED ALWAYS AS (attributes->>"$.color") VIRTUAL,
ADD INDEX (color);

优点

  • 灵活存储任意结构
  • 避免多表关联
  • 支持 JSON 路径查询
  • 可通过虚拟列建立索引

缺点

  • 需要 MySQL 5.7+
  • 数据类型验证需在应用层处理
  • 复杂查询效率较低

方案 3:关联表方案(适合固定属性)

适合已知且有限的常用属性

-- 产品表
CREATE TABLE products (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100),
  price DECIMAL(10,2)
);

-- 颜色表
CREATE TABLE product_colors (
  product_id INT PRIMARY KEY,
  color VARCHAR(50),
  FOREIGN KEY (product_id) REFERENCES products(id)
);

-- 尺寸表
CREATE TABLE product_sizes (
  product_id INT PRIMARY KEY,
  size VARCHAR(20),
  FOREIGN KEY (product_id) REFERENCES products(id)
);

优点

  • 数据结构化
  • 查询效率高
  • 可单独建立索引
  • 支持强类型约束

缺点

  • 新增属性需要修改表结构
  • 扩展性较差

推荐选择建议:

  1. 优先推荐 JSON 方案(如果使用 MySQL 5.7+)

    • 现代应用常用方案
    • 平衡了灵活性和查询效率
    • 结合虚拟列索引可解决性能问题
  2. 次选 EAV 模型(需要支持旧版本 MySQL)

    • 注意要控制属性数量
    • 建议配合缓存使用
  3. 固定属性方案(当属性非常稳定时)

    • 适合明确知道需要 color/size 等固定属性的场景

实际案例参考(JSON 方案):

-- 创建带索引的优化表
CREATE TABLE optimized_products (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100),
  price DECIMAL(10,2),
  attributes JSON NOT NULL,
  -- 生成列
  color VARCHAR(30) GENERATED ALWAYS AS (attributes->>"$.color") VIRTUAL,
  size VARCHAR(10) GENERATED ALWAYS AS (attributes->>"$.size") VIRTUAL,
  -- 建立索引
  INDEX (color),
  INDEX (size)
);

-- 查询示例(可以直接使用虚拟列)
SELECT * FROM optimized_products 
WHERE color = 'blue' AND size = 'M';

注意事项

  1. 在应用层验证数据格式(如确保 size 只能是预设值)
  2. 对高频查询的字段创建虚拟列+索引
  3. JSON 文档大小不要超过 1MB
  4. 使用 JSON_VALID() 约束保证数据有效性:
ALTER TABLE products 
ADD CONSTRAINT validate_attributes 
CHECK (JSON_VALID(attributes));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老大白菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值