摘要
本文深入解析了阿里巴巴編碼規范在數據庫設計和Java開發中的實踐應用。詳細闡述了數據庫字段命名、類型選擇、索引命名等規范,以及Java POJO類的對應規范。強調了字段命名的重要性,如布爾字段命名規則、表名和字段名的命名禁忌等。同時,介紹了主鍵、唯一索引和普通索引的區別,以及小數類型和字符串類型的選擇建議。還提出了表設計的必備字段、邏輯刪除操作、表命名規則、字段注釋更新、冗余字段使用、分庫分表等最佳實踐。
1. 【強制】表達是與否概念的字段,必須使用 is_xxx 的方式命名,數據類型是 unsigned tinyint(1 表示是,0 表示否)。
注意:POJO 類中的任何布爾類型的變量,都不要加 is 前綴,所以,需要在<resultMap>設置從 is_xxx 到 Xxx 的映射關系。數據庫表示是與否的值,使用 tinyint 類型,堅持 is_xxx 的命名方式是為了明確其取值含義與取值范圍。說明:任何字段如果為非負數,必須是 unsigned。
正例:表達邏輯刪除的字段名 is_deleted,1 表示刪除,0 表示未刪除。
1.1. 數據庫字段規范
- 表示“是/否”概念的字段(即布爾邏輯值),數據庫字段名必須是
is_xxx
的形式。 - 字段類型必須是
TINYINT(1) UNSIGNED
。
-
1
表示 是,0
表示 否。UNSIGNED
表示值非負,防止異常數據(如-1
)存入。
- 示例字段:
is_deleted TINYINT(1) UNSIGNED DEFAULT 0 COMMENT '是否已刪除:0-否,1-是'
1.2. Java 對應 POJO 類中的規范
- 在 Java Bean 中,不要將布爾變量命名為
isXxx
,而是直接命名為xxx
(符合 JavaBean 的 getter/setter 規范)。 - 對應 MyBatis 的
<resultMap>
中,應將數據庫字段is_xxx
映射到 Java 字段xxx
。
1.2.1. ? 正例示范
數據庫表結構:
CREATE TABLE user (id BIGINT PRIMARY KEY,name VARCHAR(50),is_deleted TINYINT(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否刪除,0:未刪除,1:已刪除',is_active TINYINT(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '是否激活,1:是,0:否'
);
Java 實體類:
public class User {private Long id;private String name;private Boolean deleted; // 對應 is_deletedprivate Boolean active; // 對應 is_active// Getter & Setter
}
MyBatis resultMap 映射:
<resultMap id="userMap" type="com.example.User"><id column="id" property="id"/><result column="name" property="name"/><result column="is_deleted" property="deleted"/><result column="is_active" property="active"/>
</resultMap>
1.2.2. ? 錯誤的數據庫命名:
deleted TINYINT(1)
問題:字段不明確,是否是布爾值?是否為邏輯刪除?不清晰。
1.2.3. ? 錯誤的 Java 命名:
private Boolean isDeleted;
問題:違反 JavaBean 標準(可能會導致序列化、反射或工具類識別異常)。
2. 【強制】表名、字段名必須使用小寫字母或數字,禁止出現數字開頭禁止兩個下劃線中間只出現數字。 數據庫字段名的修改代價很大,因為無法進行預發布,所以字段名稱需要慎重考慮。
說明:MySQL 在 Windows 下不區分大小寫,但在 Linux 下默認是區分大小寫。因此,數據庫名、表名、字段名,都不允許出現任何大寫字母,避免節外生枝。
正例:aliyun_admin,rdc_config,level3_name
----------------------------------------------
反例:AliyunAdmin,rdcConfig,level_3_name
2.1. 字段名、表名的命名規則
要求項 | 說明 | 示例 |
? 必須小寫 | 表名、字段名全部使用小寫字母 |
, |
? 可包含數字 | 數字可以出現但不能開頭 |
, |
? 使用下劃線分隔 | 多個單詞之間用下劃線分隔(snake_case) |
, |
? 禁止使用大寫字母 | 防止 Linux 環境下大小寫敏感導致識別錯誤 |
|
? 禁止數字開頭 | SQL 不允許以數字開頭的標識符 |
|
? 禁止兩個下劃線中只出現數字 | 防止字段難以理解、閱讀性差 |
|
2.2. ? 正確示例
類型 | 命名示例 | 說明 |
表名 |
| 小寫字母 + 下劃線 |
表名 |
| 多單詞用下劃線分隔 |
字段名 |
| 數字不能開頭,不能 |
2.3. 🚫 錯誤示例及原因
錯誤命名 | 原因說明 |
| 包含大寫字母,不兼容 Linux 下默認設置 |
| 使用了駝峰命名法,不標準 |
| 數字不能開頭 |
|
|
2.4. ?? 補充說明
- MySQL 在 Windows 是大小寫不敏感,但在 Linux 是敏感的。
- 表名、字段名一旦設計完成并投入生產,修改代價極大,涉及代碼、SQL、工具等多方調整,無法熱部署、灰度發布。
- 因此在建表、建字段初期就應當一次設計好、長期使用,統一規范是非常重要的。
3. 【強制】表名不使用復數名詞。
說明:表名應該僅僅表示表里面的實體內容,不應該表示實體數量,對應于 DO 類名也是單數形式,符合表達習慣。
4. 【強制】禁用保留字,如 desc、range、match、delayed 等,請參考 MySQL 官方保留字。
5. 【強制】主鍵索引名為 pk_字段名;唯一索引名為 uk_字段名;普通索引名則為 idx_字段名。
說明:pk_即 primary key;uk_即 unique key;idx_即 index 的簡稱。
這條規范強調數據庫索引命名應 遵循統一的命名規則,以提高可讀性、維護性和一致性。主要定義了三類索引的命名方式:
5.1. ? 命名規則說明
索引類型 | 命名格式 | 含義 |
主鍵索引 |
| Primary Key(主鍵) |
唯一索引 |
| Unique Key(唯一約束) |
普通索引 |
| Index(一般查詢優化用途) |
5.2. ? 正確示例
假設我們有一張 user
表,結構如下:
CREATE TABLE user (id BIGINT NOT NULL,username VARCHAR(50) NOT NULL,email VARCHAR(100) NOT NULL,phone VARCHAR(20),PRIMARY KEY (id),UNIQUE KEY uk_username (username),UNIQUE KEY uk_email (email),KEY idx_phone (phone)
);
解讀:
pk_id
:主鍵索引,命名為pk_id
。uk_username
:username
字段上的唯一約束,命名為uk_username。
uk_email
:email
字段上的唯一約束。idx_phone
:普通索引,用于加速對phone
字段的查詢。
5.3. ? 錯誤示例(不規范命名)
CREATE TABLE user (id BIGINT NOT NULL,username VARCHAR(50) NOT NULL,email VARCHAR(100) NOT NULL,phone VARCHAR(20),PRIMARY KEY (id),UNIQUE KEY unique_user_name (username),UNIQUE KEY EMAIL_UNIQ (email),KEY PHONE_INDEX (phone)
);
問題:
- 命名不統一,難以快速識別索引用途
- 存在大小寫混用、冗余命名(如加上
_index
)
5.4. ? 建議總結
項目 | 建議命名示例 |
主鍵 |
|
唯一索引 |
|
普通索引 |
|
5.5. ? 小貼士
- 命名使用 小寫字母 + 下劃線,符合 MySQL 通用命名規范。
- 如果是聯合索引,命名可組合字段名:
idx_userid_orderid
。 - 命名規范不僅清晰,還能便于代碼自動生成工具(如 MyBatis Generator)正確識別索引用途。
6. 主鍵(Primary Key)、唯一索引(Unique Key)和普通索引(Index)區別?
主鍵(Primary Key)、唯一索引(Unique Key)和普通索引(Index)是數據庫中三種常見的索引類型,它們的主要區別如下:
6.1. 主鍵(Primary Key)
特點
- 表中只能有一個主鍵。
- 不允許為 NULL。
- 自動創建一個唯一索引。
- 通常用于唯一標識一條記錄。
📌 示例
CREATE TABLE user (id BIGINT NOT NULL,name VARCHAR(50),PRIMARY KEY (id) -- 主鍵
);
🧠 場景
用作每行數據的唯一標識,例如 id
字段。
6.2. 唯一索引(Unique Key)
特點:
- 可以有多個唯一索引。
- 所有列的組合值必須唯一。
- 允許為 NULL(但有數據庫兼容性差異,如 MySQL 可有多個 NULL)。
示例:
CREATE TABLE user (id BIGINT NOT NULL,email VARCHAR(100),username VARCHAR(50),PRIMARY KEY (id),UNIQUE KEY uk_email (email), -- 唯一索引UNIQUE KEY uk_username (username) -- 唯一索引
);
場景:適合用于如 郵箱
、用戶名
等不允許重復的字段。
6.3. 普通索引(Index)
特點:
- 沒有唯一性限制。
- 可以創建多個普通索引。
- 主要用于加速查詢,不會約束數據唯一性。
示例:
CREATE TABLE user (id BIGINT NOT NULL,phone VARCHAR(20),PRIMARY KEY (id),KEY idx_phone (phone) -- 普通索引
);
場景:適用于頻繁用于 WHERE
、ORDER BY
的查詢字段,提高查詢性能。
6.4. 對比總結
項目 | 主鍵(Primary Key) | 唯一索引(Unique Key) | 普通索引(Index) |
是否唯一 | ? 唯一 | ? 唯一 | ? 不保證唯一 |
是否可為 NULL | ? 不可 | ? 可為 NULL(MySQL 中) | ? 可為 NULL |
數量限制 | 僅 1 個 | 多個 | 多個 |
自動索引 | ? 是 | ? 是 | ? 是 |
用途 | 主鍵標識,約束唯一 | 唯一約束某字段或組合 | 查詢加速,無約束功能 |
7. 【強制】小數類型為 decimal,禁止使用float和 double。
說明:在存儲的時候,float 和 double 都存在精度損失的問題,很可能在比較值的時候,得到不正確的結果。如果存儲的數據范圍超過 decimal 的范圍,建議將數據拆成整數和小數并分開存儲。
7.1. ? float / double:
- 屬于浮點類型,底層是二進制存儲,存在精度誤差。
- 不適合用于表示金額、利率、積分等精準計算數據。
- 比如存入
0.1
,取出來可能是0.100000001
,比較時可能出現誤判。
7.2. ? decimal(或 numeric):
- 定點數類型,可設定精確的小數位數。
- 存儲精度高,不會有精度損失。
- 非常適合用來表示金額、比例、利率、計量單位等對精度要求高的場景。
7.3. ? 錯誤示例:使用 float
CREATE TABLE order_info (order_id BIGINT PRIMARY KEY,amount FLOAT(10, 2) -- ? 錯誤,金額不能用 float
);
7.4. ? 正確示例:使用 decimal
CREATE TABLE order_info (order_id BIGINT PRIMARY KEY,amount DECIMAL(10, 2) -- ? 精確保留 2 位小數,適合金額
);
DECIMAL(10, 2)
表示總位數最多 10 位,其中小數位最多 2 位,例如最大可存儲99999999.99
。
7.5. 場景舉例
字段名稱 | 推薦類型 | 原因 |
金額 |
| 防止精度誤差 |
比例 |
| 精確表示 0.1234 |
積分 |
| 整數,不丟失精度 |
稅率 |
| 精確控制千分位 |
8. 【強制】如果存儲的字符串長度幾乎相等,使用 char 定長字符串類型。
- 如果字符串長度基本一致(差異極小,比如身份證號、手機號、MD5、UUID 等),使用
CHAR(n)
類型 - 如果長度變化較大(如評論、地址等),使用
VARCHAR(n)
8.1. 為什么選 CHAR
而不是 VARCHAR
?
- CHAR 是定長:數據庫在存儲時預留固定空間,讀取更快。
- VARCHAR 是變長:雖然節省空間,但讀取時性能略差(因為存儲時多一個字節表示長度)。
- 當字段長度固定或接近固定時,用
CHAR
可以帶來更好的查詢效率和緩存命中率。
8.2. ? 正確使用 CHAR
字段用途 | 示例字段名 | 推薦類型 | 理由 |
身份證號碼 |
|
| 長度固定 18 位 |
手機號 |
|
| 長度固定 11 位 |
UUID |
|
| 固定長度 36 字符 |
MD5 值 |
|
| MD5 長度恒定為 32 位 |
CREATE TABLE user_info (id BIGINT PRIMARY KEY,id_card_no CHAR(18) NOT NULL,phone_number CHAR(11),uuid CHAR(36)
);
8.3. ? 錯誤使用 VARCHAR
(會增加開銷)
-- 不推薦的寫法
CREATE TABLE user_info (id_card_no VARCHAR(18),phone_number VARCHAR(11)
);
- 會消耗更多 CPU 來處理長度字段。
- 在索引上也會影響查詢效率。
9. CHAR
、VARCHAR
、TEXT
、LONGTEXT
、JSON
類型怎么選擇
在設計數據庫時選擇合適的字符串類型(CHAR
、VARCHAR
、TEXT
、JSON
等)非常關鍵,它直接關系到性能、存儲、查詢能力和未來擴展性。以下是各類型的適用場景、優缺點和使用建議:
9.1. CHAR(n)
(定長字符串)
? 使用場景:
- 字段長度固定或幾乎固定,如:
-
- 身份證號(18 位)
- 手機號(11 位)
- UUID(36 位)
- 狀態碼、性別標識、等級標識等短字段
? 優點:
- 存儲效率高,查詢速度快
- 內部無需存儲長度信息(相比
VARCHAR
) - 在索引中表現更好
? 缺點:
- 會浪費空間(不足會用空格填充)
9.2. VARCHAR(n)
(變長字符串)
? 使用場景:
- 字符串長度不固定,但最大長度可預期
-
- 姓名、地址、標題、描述、郵箱、URL
- 用戶備注、標簽、崗位名稱
? 優點:
- 節省空間
- 靈活性更高
? 缺點:
- 查詢性能略差于
CHAR
- 需要額外字節存儲實際長度
9.3. TEXT
(長文本)
? 使用場景:
- 大段內容存儲,如:
-
- 文章正文、博客內容、富文本
- 聊天記錄、用戶反饋、日志內容
? 優點:
- 可存儲大容量文本(最大約 64KB)
? 缺點:
- 不能創建普通索引(要用全文索引 Fulltext)
- 查詢和排序性能低
- 不能設置默認值
- 使用時不走 InnoDB 緩存(頁緩存)
9.4. JSON
(MySQL 5.7+ 支持的 JSON 類型)
? 使用場景:
- 數據結構多變、不固定,但需結構化查詢的字段,如:
-
- 可變配置字段
- 動態參數、擴展字段(metadata)
- 日志上下文結構、第三方返回結果原始數據
? 優點:
- 可以使用 JSON 函數查詢子字段
- 數據結構靈活,不需要頻繁改表
- 比
TEXT
更可控(支持路徑查詢)
? 缺點:
- 不適合做頻繁的復雜查詢(特別是多層嵌套)
- MySQL 不對 JSON 字段做強類型校驗
- 查詢性能低于結構化字段
9.5. 數據庫字段類型選擇總結對比
類型 | 可索引 | 適合場景 | 是否支持結構化查詢 | 默認值 | 備注 |
CHAR | ? | 固定長度、標識符 | ? | ? | 性能最好,浪費空間 |
VARCHAR | ? | 一般字符串 | ? | ? | 最常用,平衡空間和性能 |
TEXT | 🚫(支持全文) | 大段文本 | ? | ? | 不可默認,不能索引排序 |
JSON | ?(僅部分支持) | 動態結構、可選字段 | ?(使用 JSON 函數) | ? | 查詢略慢,適合擴展字段 |
MySQL 中的 TEXT
并非只有一種,而是有多個變種,每種容量不同:
類型 | 最大長度(字符) | 最大容量(字節) | 描述 |
| 255 字符 | 255 字節 | 非常小的文本數據 |
| 65,535 字符 | 64 KB | 常用的一般文本 |
| 16,777,215 字符 | 16 MB | 中等大小文本,如文章、日志等 |
| 4,294,967,295 字符 | 4 GB | 超大文本,如小說、配置等 |
9.6. 使用建議(選型規則)
- 固定長度字段(手機號、身份證) →
CHAR
- 普通內容字段(姓名、地址、標題) →
VARCHAR
- 長文本內容(富文本、日志、文章) →
TEXT
- 結構不固定字段但需要查詢(配置、上下文參數) →
JSON
10. 【強制】varchar 是可變長字符串,不預先分配存儲空間,長度不要超過 5000,如果存儲長度大于此值,定義字段類型為 text,獨立出來一張表,用主鍵來對應,避免影響其它字段索引率。
11. 【強制】表必備三字段:id,create_time,update_time。
說明:其中 id 必為主鍵,類型為 bigint unsigned、單表時自增、步長為 1。create_time,update_time 的類型均為datetime 類型, 如果要記錄時區信息,那么類型設置為 timestamp。
除了【強制】的三大字段 id
、create_time
、update_time
之外,數據表設計中通常還會包含一些常用的“必要字段”,這些字段能夠增強數據管理、業務邏輯和安全性。下面給你梳理一下常見且推薦的字段:
11.1. 常見數據表必要字段匯總
字段名 | 類型 | 作用說明 | 備注 |
|
| 主鍵,自增,唯一標識一條記錄 | 必須 |
|
| 記錄創建時間 | 必須 |
|
| 記錄最后修改時間 | 必須 |
|
| 邏輯刪除標志,1=已刪除,0=未刪除 | 代替物理刪除,方便數據恢復 |
|
| 記錄創建該條數據的用戶ID | 可選,追蹤操作人 |
|
| 記錄最后修改該條數據的用戶ID | 可選,追蹤操作人 |
|
| 樂觀鎖版本號,用于控制并發更新 | 預防并發修改沖突 |
|
| 業務狀態字段,如激活、禁用、審核中等 | 業務自定義狀態碼 |
|
| 備注字段 | 可存儲補充說明 |
11.2. 數據庫設計建議
- 邏輯刪除字段
is_deleted
,避免直接物理刪除,方便數據恢復與審計。 - 操作用戶字段
create_user
和update_user
,便于追蹤責任。 - 樂觀鎖字段
version
,防止數據被并發修改導致不一致。 - 狀態字段
status
,統一管理業務狀態,方便業務流程控制。 - 備注字段
remark
,記錄額外信息,便于維護和擴展。
CREATE TABLE example_entity (id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,is_deleted TINYINT UNSIGNED NOT NULL DEFAULT 0,create_user BIGINT UNSIGNED, -- 適合采用用戶id 而不是采用字符類型update_user BIGINT UNSIGNED, -- 適合采用用戶id 而不是采用字符類型create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,version INT UNSIGNED NOT NULL DEFAULT 0,status TINYINT UNSIGNED NOT NULL DEFAULT 1,remark VARCHAR(255)
);
12. 【強制】在數據庫中不能使用物理刪除操作,要使用邏輯刪除。
說明:邏輯刪除在數據刪除后可以追溯到行為操作。不過會使得一些情況下的唯一主鍵變得不唯一,需要根據情況來酌情解決。
13. 【推薦】表的命名最好是遵循“業務名稱表的作用”
正例:alipay_task / force_project / trade_config / tes_question
14. 【推薦】庫名與應用名稱盡量一致。
15. 【推薦】如果修改字段含義或對字段表示的狀態追加時,需要及時更新字段注釋。
16. 【推薦】字段允許適當冗余, 以提高查詢性能, 但必須考慮數據一致。 冗余字段應遵循:
- 不是頻繁修改的字段。
- 不是唯一索引的字段。
- 不是 varchar 超長字段,更不能是 text 字段。
正例:各業務線經常冗余存儲商品名稱,避免查詢時需要調用 IC 服務獲取。
17. 【推薦】單表行數超過 500 萬行或者單表容量超過 2GB, 才推薦進行分庫分表。
說明:如果預計三年后的數據量根本達不到這個級別,請不要在創建表時就分庫分表。
這條建議是基于實際項目中分庫分表的復雜度和維護成本而總結的經驗,確實很有參考價值。下面我幫你詳細說明實際情況和背后的考慮:
17.1. 實際情況分析:
單表數據量和性能瓶頸
- 單表數據量超過 幾百萬行,數據庫的查詢性能、索引維護、備份恢復等都會受到影響,尤其是沒有做合理索引和查詢優化時。
- 表容量超過 2GB,尤其是普通的 OLTP 場景,可能導致 I/O 壓力變大,查詢響應變慢。
- 但具體影響還依賴于硬件性能、數據庫版本、存儲引擎(InnoDB等)、緩存配置等。
分庫分表的復雜度
- 設計分庫分表架構,代碼復雜度大幅提升,開發和運維成本高。
- 涉及跨庫事務處理難度大,分布式事務開銷大,調試復雜。
- 預先分庫分表可能帶來不必要的系統復雜度和風險。
業務增長預估與實際
- 很多項目上線初期數據量較小,提前做分庫分表導致資源浪費和開發負擔。
- 預測三年后的數據量不到 500 萬或容量不到 2GB,完全可以先用單庫單表,后期再擴展。
- 可以結合歸檔策略、清理機制等避免數據爆表。
分庫分表時機
- 實際上很多大公司都是業務增長到瓶頸才開始分庫分表,采用平滑遷移方案。
- 使用中間件(如 MyCat、ShardingSphere)或自研分片邏輯,逐步遷移。
17.2. 總結建議:
條件 | 推薦做法 |
數據量 < 500萬行,容量 < 2GB | 單庫單表即可,先保證穩定 |
數據量接近或超過 500萬行,容量 > 2GB | 評估是否做分表,考慮讀寫壓力 |
業務增長迅速,數據爆發式增長 | 盡早設計分庫分表方案 |
17.3. 實際案例
- 小型項目:幾萬到幾十萬條數據,一張表即可,簡單易維護。
- 中型系統:百萬級數據,優化索引、分區表,暫不分庫。
- 大型互聯網應用:幾千萬甚至億級數據,分庫分表必不可少。
博文參考
《阿里巴巴java規范》