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

MySQL 性能優化全攻略:SHOW、EXPLAIN、慢查詢、索引優化實戰

     編輯:MySQL 資料庫相關知識

內建工具三板斧:SHOW、EXPLAIN、慢查詢日誌

1. SHOW:洞察服務器運行狀態

-- 全局狀態變量(重點關注)
SHOW GLOBAL STATUS;

-- 關鍵指標解讀
-- Aborted_connects      連接嘗試失敗數
-- Connections           總連接嘗試數
-- Max_used_connections  歷史峰值併發連接數
-- Threads_connected     當前打開連接數
-- Threads_running       當前活躍查詢線程數
-- Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests  緩衝池命中率
-- Created_tmp_disk_tables  磁盤臨時表數(應盡量為 0)
-- Select_scan           全表掃描次數
-- Sort_merge_passes     排序溢寫磁盤次數

其他實用 SHOW 變體

命令用途
SHOW PROCESSLIST當前線程列表,排查長事務、鎖等待
SHOW ENGINE INNODB STATUSInnoDB 內部狀態:鎖、事務、死鎖、緩衝池、插入緩衝
SHOW TABLE STATUS LIKE 'tbl'表統計:行數、數據長度、索引長度、自增值、碎片率
SHOW INDEX FROM tbl索引詳情:基數、前綴長度、是否唯一
SHOW VARIABLES LIKE 'innodb%'InnoDB 參數快速查閱
SHOW CREATE TABLE tbl獲取建表 DDL,含分區、外鍵、字符集

2. EXPLAIN:查詢執行計劃解剖刀

經典優化案例:多表連接從 ALL 到 ref

-- 原始查詢
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn, et.COUNTRY, do.CUSTNAME
FROM tt, et, et AS et_1, do
WHERE tt.SubmitTime IS NULL
  AND tt.ActualPC = et.EMPLOYID
  AND tt.AssignedPC = et_1.EMPLOYID
  AND tt.ClientID = do.CUSTNMBR;

表結構與索引現狀:

表列類型索引
ttActualPCCHAR(10)有
ttAssignedPCCHAR(10)有
ttClientIDCHAR(10)有
etEMPLOYIDCHAR(15) PK主鍵
doCUSTNMBRCHAR(15) PK主鍵

EXPLAIN 初始輸出(全 ALL,笛卡爾積 450 億行):

table  type  possible_keys      key   key_len  ref   rows    Extra
et     ALL   PRIMARY            NULL  NULL     NULL  74
do     ALL   PRIMARY            NULL  NULL     NULL  2135
et_1   ALL   PRIMARY            NULL  NULL     NULL  74
tt     ALL   AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 range checked...

問題根因:列長度不匹配導致索引失效

  • tt.ActualPC CHAR(10) vs et.EMPLOYID CHAR(15) → 隱式轉換,索引不可用。
  • tt.ClientID CHAR(10) vs do.CUSTNMBR CHAR(15) → 同理。

優化步驟

  1. 修正列定義:ALTER TABLE tt MODIFY ActualPC CHAR(15); 等,或修改被引用表列長度(視業務影響)。
  2. 補充聯合索引:ALTER TABLE tt ADD INDEX idx_submit_actual (SubmitTime, ActualPC);
  3. 重新 EXPLAIN 驗證:type 變為 ref/eq_ref,rows 驟降。

EXPLAIN 關鍵列速查

列含義優秀值警惕值
id查詢序號——
select_type查詢類型SIMPLE, PRIMARYDEPENDENT SUBQUERY, UNCACHEABLE SUBQUERY
table訪問表——
partitions分區——
type訪問類型system, const, eq_ref, ref, range, indexALL (全表掃描)
possible_keys候選索引有具體名NULL
key實際用索引有具體名NULL
key_len索引鍵長盡可能短過長(含 NULL、可變長)
ref關聯列/常量——
rows預估掃描行越小越好巨大(百萬+)
Extra額外信息Using index, Using whereUsing temporary, Using filesort, Range checked for each record

3. 慢查詢日誌:發現問題的雷達

[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 0.5          -- 秒,生產建議 0.5-1
log_queries_not_using_indexes = 1
log_slow_admin_statements = 1
log_slow_slave_statements = 1

分析神器:pt-query-digest

pt-query-digest /var/log/mysql/slow.log --limit 20 --filter '$event->{fingerprint} !~ /^SET/'

# 輸出 Top SQL:執行次數、總時間、平均時間、掃描行數、指紋、樣本 SQL

索引優化實戰清單

  1. 覆蓋索引:SELECT a, b FROM t WHERE c = 1 → INDEX idx_c_ab (c, a, b),Extra: Using index。
  2. 最左前綴:INDEX (a, b, c) 支持 a/a,b/a,b,c。
  3. 避免函數殺索引:WHERE DATE(created) = '2023-01-01' → WHERE created >= '2023-01-01' AND created < '2023-01-02'。
  4. 主鍵選擇:自增整型 > UUID > 業務鍵;InnoDB 聚簇索引順序寫入減少頁分裂。
  5. 定期維護:ANALYZE TABLE 更新統計信息;OPTIMIZE TABLE 整理碎片(或 ALTER TABLE ... ENGINE=InnoDB)。

系統參數調優速查(InnoDB 核心)

參數建議值說明
innodb_buffer_pool_size物理內存 60%-80%核心緩衝池,數據+索引+鎖+插入緩衝
innodb_log_file_size1GB-4GBRedo log 大小,減少 checkpoint 衝刷
innodb_log_buffer_size64MB-256MB事務日誌緩衲,大事務調大
innodb_flush_log_at_trx_commit1 (安全) / 2 (性能)1=每次提交刷盤,2=每秒刷盤
innodb_file_per_tableON獨立表空間,便於回收空間
innodb_read_io_threads / write_io_threads4-16後台 IO 線程,SSD 可調大
max_connections應用峰值 * 1.5防止 Too many connections
query_cache_type / sizeOFF / 0MySQL 5.7+ 建議關閉,8.0 已移除

總結

MySQL 性能優化遵循 「監控 → 發現 → 分析 → 優化 → 驗證」 閉環:

  1. 用 SHOW GLOBAL STATUS、慢查詢日誌 發現瓶頸。
  2. 用 EXPLAIN 剖析執行計劃,定位 ALL、Using temporary、filesort、索引失效。
  3. 從 SQL 改寫、索引調整、表結構優化、參數調優 四個維度入手,優先 SQL 與索引(ROI 最高)。
  4. 壓測驗證,觀察 Rows_examined、Query_time、Innodb_buffer_pool_reads 等指標下降。

工欲善其事,必先利其器。熟練掌握 SHOW/EXPLAIN/慢查詢三板斧,是每個 DBA 與後端工程師的必修課。

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