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

MySQL PROCEDURE ANALYSE() 實戰:讓數據庫自動推薦最優列類型與優化建議

     編輯:MySQL 綜合教學

MySQL 內建 PROCEDURE ANALYSE() 可對查詢結果集進行統計分析,自動推薦每列的**最優數據類型**、**是否可 NOT NULL**、**ENUM 適用性**等優化建議。雖 MySQL 8.0 已標記棄用(改用 ANALYZE TABLE 統計信息),但在 5.7/舊版本快速審計表結構、發現過度設計類型(如 BIGINT 存狀態碼)仍極具價值。本文詳解語法、輸出解讀、實戰案例與替代方案。

語法與參數

SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements, [max_memory]]);

-- 參數說明
max_elements (默認 256): 分析每列不重複值上限,超過則不建議 ENUM
max_memory (默認 8192): 分析過程最大內存分配(字節)

實戰演示

建立測試表

CREATE TABLE user_account (
  USERID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  USERNAME VARCHAR(10) NOT NULL,
  PASSWORD VARCHAR(30) NOT NULL,
  GROUPNAME VARCHAR(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO user_account (USERNAME, PASSWORD, GROUPNAME) VALUES
('admin', 'hash1', 'admins'),
('user1', 'hash2', 'users'),
('user2', 'hash3', 'users'),
('guest', 'hash4', 'guests');

執行分析

SELECT * FROM user_account PROCEDURE ANALYSE(16, 256)\G

輸出字段解讀

輸出字段含義決策參考
Field_name庫.表.列定位對象
Min_value / Max_value樣本最小/最大值判斷範圍、是否需 UNSIGNED
Min_length / Max_length值字符串長度範圍決定 VARCHAR/CHAR 長度
Empties_or_zeros空值/零值計數決定 NOT NULL
NullsNULL 值計數決定 NOT NULL
Avg_value_or_avg_length平均值/平均長度評估類型大小
Std標準差分布離散度
Optimal_fieldtype推薦最優類型核心輸出,直接可用於 ALTER TABLE

範例輸出解析

*************************** 1. row ***************************
Field_name: test.user_account.USERID
Min_value: 1
Max_value: 4
Min_length: 1
Max_length: 1
Empties_or_zeros: 0
Nulls: 0
Avg_value_or_avg_length: 2.5000
Std: 1.2909
Optimal_fieldtype: TINYINT(3) UNSIGNED NOT NULL
  → 當前 INT(10) 過大,實際僅 4 行,建議縮小為 TINYINT UNSIGNED

*************************** 2. row ***************************
Field_name: test.user_account.USERNAME
Min_value: admin
Max_value: user2
Min_length: 4
Max_length: 5
Empties_or_zeros: 0
Nulls: 0
Avg_value_or_avg_length: 4.5000
Std: 0.5773
Optimal_fieldtype: VARCHAR(5) NOT NULL
  → 當前 VARCHAR(10) 可縮為 VARCHAR(5)

*************************** 3. row ***************************
Field_name: test.user_account.GROUPNAME
Min_value: admins
Max_value: users
Min_length: 5
Max_length: 6
Empties_or_zeros: 0
Nulls: 1
Optimal_fieldtype: ENUM('admins','guests','users') NOT NULL
  → 僅 3 個不同值,且無 NULL(樣本中有 1 NULL 但建議 NOT NULL),極適合 ENUM

適用場景與局限

適用場景不適用/局限
繼承舊系統,快速審計數百張表類型過度設計MySQL 8.0 棄用,未來版本移除
開發期樣本數據較全,輔助定型樣本不全(如缺極值)會給出錯誤建議
發現 BIGINT 存狀態碼、VARCHAR(255) 存性別等明顯浪費不分析索引、外鍵、分區等結構
配合 pt-online-schema-change 安全變更類型大表執行慢、佔用內存、可能鎖表

MySQL 8.0 現代替代方案

1. ANALYZE TABLE 更新統計信息

ANALYZE TABLE user_account;  -- 更新索引基數統計,優化器受益

2. INFORMATION_SCHEMA.COLUMNS + 統計查詢自建分析

SELECT 
  c.COLUMN_NAME, c.COLUMN_TYPE, c.IS_NULLABLE,
  (SELECT COUNT(DISTINCT c.COLUMN_NAME) FROM user_account) AS distinct_cnt,
  (SELECT MAX(CHAR_LENGTH(c.COLUMN_NAME)) FROM user_account) AS max_len,
  (SELECT MIN(CHAR_LENGTH(c.COLUMN_NAME)) FROM user_account) AS min_len
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_SCHEMA = 'test' AND c.TABLE_NAME = 'user_account';

3. 結合 performance_schema 觀察實際查詢模式

SELECT 
  DIGEST_TEXT, COUNT_STAR, AVG_TIMER_WAIT/1e12 AS avg_sec
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST_TEXT LIKE '%user_account%'
ORDER BY AVG_TIMER_WAIT DESC LIMIT 10;

安全變更類型檢查清單

  1. ✅ 完整備份或快照
  2. ✅ 驗證推薦類型能容納**未來增長**(預留 10x 空間)
  3. ✅ 檢查應用層代碼:ORM 實體類型、DTO 驗證、序列化邏輯
  4. ✅ 使用 pt-online-schema-change 或 gh-ost 在線變更(無鎖)
  5. ✅ 灰度發布:先測試環境、再預發布、最後生產
  6. ✅ 回滾預案:保留舊表結構腳本、數據導出腳本

一鍵批量審計腳本(5.7 適用)

#!/bin/bash
# analyse_all_tables.sh
DB="your_db"
mysql -N -e "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='$DB'" | \
while read table; do
  echo "=== $table ==="
  mysql -e "SELECT * FROM \`$DB\`.\`$table\` PROCEDURE ANALYSE(100, 1024)\G" 2>/dev/null | \
  grep -E 'Field_name|Optimal_fieldtype'
done
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved