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

MySQL Sending data 慢查詢根因:大字段溢出頁導致隨機 I/O 暴增

     編輯:MySQL 綜合教學

MySQL Sending data 慢查詢根因:大字段溢出頁導致隨機 I/O 暴增

Sphinx 同步幾萬行數據卻跑 4-5 分鐘,EXPLAIN 顯示索引正常,SHOW PROCESSLIST 長期卡在 Sending data。本文通過 SHOW PROFILE 定位到 VARCHAR(8000) 大字段,揭示 InnoDB COMPACT 行格式下溢出頁不入緩衝池的機制。

現象與定位

  • 查詢返回含 description VARCHAR(8000) 的表
  • EXPLAIN:索引正常,首表全掃描(業務必需)
  • SHOW PROCESSLIST:長期 Sending data
  • SHOW PROFILE:Sending data 耗時 216 秒

EXPLAIN 正常

Sending data 狀態

Profile 216秒

對比實驗

查詢耗時倍數
不返回 description15 秒1x
返回 description216 秒14.4x

不返回description 15秒

核心原理:InnoDB 溢出頁機制

COMPACT/REDUNDANT 行格式:
- 行內存前 768 字節
- 超出部分存入 溢出頁(Uncompressed BLOB 頁)
- 讀取需「主頁 → 溢出頁」雙重查找,變順序讀為隨機讀

關鍵發現:SHOW TABLE STATUS 顯示平均行長 1.5KB,約 1/10 行用溢出頁。
表狀態

更關鍵:**溢出頁不進入 Buffer Pool**。反覆執行同一查詢、甚至全表掃描,速度不變,證明溢出頁每次都從磁盤讀取。設計邏輯:防止大對象沖刷熱點頁。

解決方案對比

方案優點缺點適用性
1. 查詢不選大字段零改動、立竿見影業務可能強制需要✅ 首選
2. 垂直拆表主表變窄、索引緩存命中率升改動大、若仍頻繁 JOIN 大字段表收益有限✅ 徹底治本
3. 改用 DYNAMIC/COMPRESSED 行格式大字段全外置、主頁更緊湊需重建表、溢出頁仍不緩存⚠️ 輔助
4. 外部存儲(對象存儲/文件系统)DB 極瘦、海量大對象友好架構複雜、一致性需應用層保證✅ 架構級方案

最佳實踐建議

  1. 表設計階段:大文本/Blob **強制拆表** 或外部存儲
  2. 已有表:ALTER TABLE ... ROW_FORMAT=DYNAMIC 重建(需停機或 pt-online-schema-change)
  3. 查詢層:SELECT id, col1, col2 避免 SELECT *
  4. 監控:關注 Innodb_buffer_pool_pages_flushed、Innodb_data_reads 飆升
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved