首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

資料庫結構重構實戰:從多索引到利用主鍵索引的極致優化

     編輯:MySQL 綜合教學

資料庫結構重構實戰:從多索引到利用主鍵索引的極致優化

在高併發寫入場景下,盲目添加二級索引往往因維護成本導致寫入效能雪崩。本文通過一個消息表的真實優化案例,展示如何通過結構重構、業務邏輯下沉,在不增加任何新索引的前提下,將百萬級數據查詢從 4.75 秒降至 0.0001 秒,實現讀寫效能的雙贏。

問題場景:消息表的索引困境

原表結構:

CREATE TABLE chat_message (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    content TEXT,
    user_id BIGINT,
    is_wonderful TINYINT,   -- 是否精彩發言
    is_top TINYINT,         -- 是否置頂
    is_barrage TINYINT      -- 是否彈幕
);

業務需頻繁查詢「精彩發言」「置頂消息」「彈幕消息」。數據量達 37 萬時,全表掃描耗時 4.75 秒。雖加索引可降至 0.1 秒,但每新增一個索引,寫入延遲明顯上升;三個業務欄位若全建索引,高頻寫入場景下將嚴重拖慢吞吐。

核心洞察:主鍵索引的隱性優勢

InnoDB 聚簇索引特性決定:主鍵索引葉子節點直接存放完整行數據,二級索引葉子節點僅存主鍵值,查詢需「回表」。若能將篩選條件轉化為主鍵範圍掃描,即可繞過二級索引,直接利用聚簇索引有序性實現極速查詢。

重構方案:業務表 + 類型映射表

步驟 1:抽離業務屬性,建立映射表

CREATE TABLE message_type_ref (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    type TINYINT NOT NULL COMMENT '1-精彩 2-置頂 3-彈幕',
    chat_message_id BIGINT NOT NULL,
    INDEX idx_type (type)  -- 僅此一個輔助索引
);

步驟 2:查詢邏輯轉換

  • 原查詢:SELECT * FROM chat_message WHERE is_wonderful = 1(全表掃描/二級索引回表)
  • 新查詢:SELECT cm.* FROM chat_message cm JOIN message_type_ref mtr ON cm.id = mtr.chat_message_id WHERE mtr.type = 1

映射表 idx_type 快速定位符合類型的主鍵 ID,再回主表按主鍵批量查詢。因主鍵有序,InnoDB 可執行高效的 Range Scan,且無額外回表開銷。

實測數據對比

指標原方案(全表掃描)加三個二級索引重構方案(映射表)
查詢耗時 (37 萬行)4.753 秒~0.1 秒0.0001 秒
寫入影響基準每索引 +5~15% 延遲僅維護 1 張小表索引,影響可忽略
索引維護成本03 個二級索引1 個小表索引
存儲開銷基準+3 × 索引大小+ 映射表 (極小)

EXPLAIN 驗證:完美利用主鍵索引

EXPLAIN SELECT cm.* FROM chat_message cm
JOIN message_type_ref mtr ON cm.id = mtr.chat_message_id
WHERE mtr.type = 1;
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | mtr   | NULL       | ref  | idx_type      | idx_type | 1       | const |  100 |   100.00 | Using index |
|  1 | SIMPLE      | cm    | NULL       | eq_ref | PRIMARY     | PRIMARY  | 8       | mtr.chat_message_id |    1 |   100.00 | NULL        |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+

映射表走 ref 類型命中 idx_type,主表走 eq_ref 直接命中 PRIMARY,零回表、零臨時表、零文件排序。

設計原則總結

  1. 寫入敏感表極簡索引:核心業務表僅保留主鍵,避免二級索引寫放大。
  2. 業務屬性外置映射:將低基數、高頻篩選屬性抽離為「類型-主鍵」映射表,利用小表索引 + 主鍵回表模式。
  3. 利用聚簇索引有序性:主鍵範圍查詢極快,設計時讓高頻查詢轉化為主鍵 IN/Range 條件。
  4. 權衡讀寫比例:唯讀/低寫場景可直建二級索引;高寫場景優先考慮結構重構。

此模式適用於「標籤/狀態/分類」等低基數屬性頻繁篩選的高寫入表,是「以空間換時間、以結構換索引」的經典實踐。

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