「足夠用、最小型、避免隱式轉換」 — 合適的數據類型能節省存儲、提升查詢效能、減少隱式轉換導致的索引失效。
| 類型 | 存儲 | 有符號範圍 | 無符號範圍 | 典型應用 |
|---|---|---|---|---|
| TINYINT | 1 字節 | -128 ~ 127 | 0 ~ 255 | 年齡、狀態碼、布爾值(0/1)、小枚舉 |
| SMALLINT | 2 字節 | -32,768 ~ 32,767 | 0 ~ 65,535 | 郵編、中型計數器 |
| MEDIUMINT | 3 字節 | -8,388,608 ~ 8,388,607 | 0 ~ 16,777,215 | **自增 ID 首選** (千萬級以內業務)、中型統計 |
| INT / INTEGER | 4 字節 | -21億 ~ 21億 | 0 ~ 42億 | 通用 ID、大計數器 (但常過大造成浪費) |
| BIGINT | 8 字節 | -922京 ~ 922京 | 0 ~ 1844京 | 超大數值、分布式 ID (Snowflake)、高精度時間戳 |
建議: 自增主鍵優先用 MEDIUMINT UNSIGNED (1600 萬) 或 INT UNSIGNED (42 億),除非確定超過範圍才用 BIGINT。**不要默認用 INT** — 3 字節 vs 4 字節,億級表每節省 1 字節可省數百 MB 存儲與內存。
DECIMAL(M,D) / NUMERIC(M,D):M=總位數(精度),D=小數位數(標度)price DECIMAL(10,2) 支援 99,999,999.99| 類型 | 存儲 | 精度 | 最小正值 | 適用場景 |
|---|---|---|---|---|
| FLOAT | 4 字節 | ~7 位有效數字 | 1.17E-38 | 科學計算、坐標、非精確測量值 |
| DOUBLE | 8 字節 | ~15 位有效數字 | 2.22E-308 | 高精度科學計算、地理空間 |
禁忌: **絕不可用於金額計算**,0.1 + 0.2 != 0.3 在浮點數中成立。
| 類型 | 存儲 | 範圍 | 精度 | 時區處理 | 推薦場景 |
|---|---|---|---|---|---|
| DATE | 3 字節 | 1000-01-01 ~ 9999-12-31 | 天 | 無 | 生日、入職日期、純業務日期 |
| TIME | 3 字節 | -838:59:59 ~ 838:59:59 | 秒 (可微秒) | 無 | 每日定時任務時間、持續時長 |
| DATETIME | 8 字節 (5.6.4+ 可 5+字節) | 1000 ~ 9999 年 | 秒 (可微秒) | **不轉換** (存什麼讀什麼) | 業務時間、日誌記錄、需保留原始輸入 |
| TIMESTAMP | 4 字節 | 1970-01-01 ~ 2038-01-19 | 秒 (可微秒) | **自動轉換** (存儲時轉 UTC,讀取轉會話時區) | 創建/更新時間戳、跨時區應用、自動更新 |
| YEAR | 1 字節 | 1901 ~ 2155 | 年 | 無 | 年份篩選、年度報表 |
選型決策樹:
DATEDATETIMETIMESTAMP (注意 2038 年問題)DATETIME(3) 支援毫秒,存儲更優,推薦替代 TIMESTAMP| 類型 | 存儲特性 | 最大長度 | 適用場景 | 避坑指南 |
|---|---|---|---|---|
| CHAR(N) | 固定長度,不足右補空格 | 255 字符 | 長度固定、極短 (如 MD5 32位、UUID 36位、身份證 18位、ISO 代碼) | 變長數據用 CHAR 極度浪費空間並導致尾部空格比較問題 |
| VARCHAR(N) | 變長,1-2 字節存長度 + 實際內容 | 65,535 字節 (共享行上限) | 長度可變的文本:名稱、標題、描述、JSON 片段 | N 設過大影響內存臨時表效能,實際最長 200 設 200 而非 255 |
| TEXT | 溢出頁存儲,指針在行內 | 64 KB | 長文本:文章內容、日誌詳情 | 不建議建索引 (需指定前綴長度),SELECT * 會讀取溢出頁 |
| BLOB | 二進制 TEXT | 64 KB | 圖片、文件、加密數據 | 同 TEXT,區別在於二進制比較、無字符集 |
最佳實踐:
CHARVARCHAR + 合理長度TEXT 並拆分到擴展表,主表只存核心字段utf8mb4 (支援 Emoji),排序規則 utf8mb4_general_ci 或 0900_ai_ciENUM('男','女')、狀態 ENUM('pending','paid','shipped','closed')TINYINT 更語義化,比 VARCHAR 省空間、比較快ALTER TABLE,排序按定義順序而非字符順序SET('read','write','delete','admin')、文章標籤FIND_IN_SET('read', perm_set)、perm_set & 1 (位運算)| 業務場景 | 推薦類型 | 關鍵理由 |
|---|---|---|
| 自增主鍵 (千萬級) | MEDIUMINT UNSIGNED | 3字節,足夠大,省空間 |
| 分布式 ID / 雪花算法 | BIGINT UNSIGNED | 64位整數完美承接 |
| 商品價格 / 費率 | DECIMAL(10,2) / DECIMAL(5,4) | 精確計算,無浮點誤差 |
| 用戶年齡 | TINYINT UNSIGNED | 1字節,0-255 足夠 |
| 創建時間 (跨時區) | TIMESTAMP / DATETIME(3) | 自動時區轉換 / 毫秒精度無2038問題 |
| 身份證號 | CHAR(18) | 固定18位,CHAR最優 |
| 文章標題 | VARCHAR(200) | 可變長度,限制合理上限 |
| 訂單狀態 | ENUM('created','paid','shipped','done','cancelled') | 語義化、緊湊、快速比較 |
| 用戶權限標籤 | SET('user','vip','admin','super') | 位掩碼高效多選 |