首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 與 MongoDB 設計實戰對比:手機產品屬性建模的關係型 vs 文檔型抉擇

     編輯:MySQL 資料庫相關知識

關係型資料庫 (MySQL) 與文檔型資料庫 (MongoDB) 在處理「動態屬性」場景下的設計差異巨大。以手機產品庫為例,深度對比兩種建模思路、查詢模式與擴展性。

業務場景

  • 核心屬性:名稱、品牌(相對固定)。
  • 動態屬性:待機時間、外觀設計、螢幕尺寸、電池容量...(機型差異大、頻新增)。
  • 查詢需求:多條件組合篩選(如:待機 > 100h AND 外觀 = 直板)。

MySQL 方案:EAV (Entity-Attribute-Value) 模式

表結構

CREATE TABLE `mobiles` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(100) NOT NULL,
  `brand` VARCHAR(100) NOT NULL
) ENGINE=InnoDB;

CREATE TABLE `mobile_params` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `mobile_id` INT UNSIGNED NOT NULL,
  `name` VARCHAR(100) NOT NULL,
  `value` VARCHAR(100) NOT NULL,
  INDEX `idx_mobile_id` (`mobile_id`),
  INDEX `idx_name_value` (`name`, `value`)
) ENGINE=InnoDB;

資料樣本

INSERT INTO `mobiles` VALUES (1, 'ME525', '摩托羅拉'), (2, 'E7', '諾基亞');
INSERT INTO `mobile_params` VALUES 
(1, 1, '待機時間', '200'), (2, 1, '外觀設計', '直板'),
(3, 2, '待機時間', '500'), (4, 2, '外觀設計', '滑蓋');

多條件查詢(需自行交集)

-- 步驟 1:查待機 > 100 的 mobile_id
SELECT `mobile_id` FROM `mobile_params` WHERE `name`='待機時間' AND CAST(`value` AS UNSIGNED) > 100;
-- 步驟 2:查外觀 = 直板 的 mobile_id
SELECT `mobile_id` FROM `mobile_params` WHERE `name`='外觀設計' AND `value`='直板';
-- 步驟 3:應用層取交集 → 查 mobiles 主表

痛點: 字串儲存數值需 CAST、多條件需多查詢/自交集、索引效率低、Schema 變更仍需 DDL。

MongoDB 方案:內嵌文檔 + 陣列索引

文檔結構

db.mobiles.createIndex({ "params.name": 1, "params.value": 1 });

db.mobiles.insert({
  _id: 1, name: "ME525", brand: "摩托羅拉",
  params: [
    { name: "待機時間", value: 200 },
    { name: "外觀設計", value: "直板" }
  ]
});

db.mobiles.insert({
  _id: 2, name: "E7", brand: "諾基亞",
  params: [
    { name: "待機時間", value: 500 },
    { name: "外觀設計", value: "滑蓋" }
  ]
});

單查詢完成多條件篩選

db.mobiles.find({
  params: {
    $all: [
      { $elemMatch: { name: "待機時間", value: { $gt: 100 } } },
      { $elemMatch: { name: "外觀設計", value: "直板" } }
    ]
  }
});
  • $all:陣列需同時滿足所有條件。
  • $elemMatch:單一陣列元素同時滿足多欄位條件(避免跨元素誤匹配)。
  • 型別原生支援:value 可為數值/字串/布林/日期,查詢運算子($gt、$lt)直接生效。

多維深度對比

維度MySQL (EAV)MongoDB (文檔)
建模複雜度中(需設計參數表)低(自然映射物件)
動態屬性新增無需 DDL,僅寫入參數表無需 DDL,直接寫入文檔
多條件查詢多 SQL + 應用層交集 / 複雜自連接單查詢 ($all + $elemMatch)
型別安全弱(全存字串,需 CAST)強(原生型別)
索引效率參數表索引碎片化、選擇度低複合陣列索引精準命中
事務/一致性強 (ACID)文檔級 ACID (4.0+ 多文檔事務)
擴展性垂直分表/分庫分表原生 Sharding
運維成熟度極高高(但需專業知識)

MySQL 進階優化:JSON 欄位 (5.7+) 縮小差距

CREATE TABLE `mobiles_v2` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(100), `brand` VARCHAR(100),
  `params` JSON NOT NULL,
  INDEX `idx_params_standby` ((CAST(JSON_EXTRACT(`params`, '$.待機時間') AS UNSIGNED))),
  INDEX `idx_params_design` ((CAST(JSON_EXTRACT(`params`, '$.外觀設計') AS CHAR(20))))
) ENGINE=InnoDB;

INSERT INTO `mobiles_v2` VALUES 
(1, 'ME525', '摩托羅拉', '{"待機時間": 200, "外觀設計": "直板"}'),
(2, 'E7', '諾基亞', '{"待機時間": 500, "外觀設計": "滑蓋"}');

-- 查詢
SELECT * FROM `mobiles_v2` 
WHERE JSON_EXTRACT(`params`, '$.待機時間') > 100 
  AND JSON_EXTRACT(`params`, '$.外觀設計') = '直板';
  • 虛擬欄位索引實現類 MongoDB 查詢效能。
  • 保留關係型優勢(事務、成熟生態、SQL 標準)。

選型決策建議

業務核心是否為「動態屬性多條件查詢」?
├─ 是,且團隊具備 MongoDB 運維能力 → MongoDB 為首選
│
├─ 否,或堅持關係型生態 → MySQL 5.7+ JSON + 虛擬欄位索引
│
├─ 極簡場景、屬性固定化 → MySQL 傳統欄位/關聯表
│
└─ 混合負載 → 核心交易 MySQL,動態屬性/搜尋/日誌 MongoDB/ES

本例中 MongoDB 以單查詢解決 MySQL 需多步驟的問題,展現文檔模型在**半結構化、動態屬性、多條件組合篩選**場景的原生優勢。但選型從來不只是看單一場景,需綜合團隊技術棧、一致性要求、運維成熟度、成本預算決策。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved