方案 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)
);
優點:
- 數據結構化
- 查詢效率高
- 可單獨建立索引
- 支持強類型約束
缺點:
- 新增屬性需要修改表結構
- 擴展性較差
推薦選擇建議:
-
優先推薦 JSON 方案(如果使用 MySQL 5.7+)
- 現代應用常用方案
- 平衡了靈活性和查詢效率
- 結合虛擬列索引可解決性能問題
-
次選 EAV 模型(需要支持舊版本 MySQL)
- 注意要控制屬性數量
- 建議配合緩存使用
-
固定屬性方案(當屬性非常穩定時)
- 適合明確知道需要 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';
注意事項:
- 在應用層驗證數據格式(如確保 size 只能是預設值)
- 對高頻查詢的字段創建虛擬列+索引
- JSON 文檔大小不要超過 1MB
- 使用
JSON_VALID()
約束保證數據有效性:
ALTER TABLE products
ADD CONSTRAINT validate_attributes
CHECK (JSON_VALID(attributes));