阿里java開發規範(6)---MySQL資料庫
五、 MySQL 資料庫
(一)建表規約1. 【強制】表達是與否概念的欄位,必須使用 is_xxx 的方式命名,資料型別是 unsigned tinyint
( 1 表示是, 0 表示否)。
說明: 任何欄位如果為非負數,必須是 unsigned。
注意: POJO 類中的任何布林型別的變數,都不要加 is 字首,所以,需要在<resultMap>設定
從 is_xxx 到 Xxx 的對映關係。資料庫表示是與否的值,使用 tinyint 型別,堅持 is_xxx 的
命名方式是為了明確其取值含義與取值範圍。
正例: 表達邏輯刪除的欄位名 is_deleted, 1 表示刪除, 0 表示未刪除。
2.
出現數字。資料庫欄位名的修改代價很大,因為無法進行預釋出,所以欄位名稱需要慎重考慮。
說明: MySQL 在 Windows 下不區分大小寫,但在 Linux 下預設是區分大小寫。因此,資料庫名、
表名、欄位名,都不允許出現任何大寫字母,避免節外生枝。
正例: aliyun_admin, rdc_config, level3_name
反例: AliyunAdmin, rdcConfig, level_3_name
3. 【強制】表名不使用複數名詞。
說明: 表名應該僅僅表示表裡面的實體內容,不應該表示實體數量,對應於 DO
形式,符合表達習慣。
4. 【強制】禁用保留字,如 desc、 range、 match、 delayed 等, 請參考 MySQL 官方保留字。
5. 【強制】 主鍵索引名為 pk_欄位名; 唯一索引名為 uk_欄位名; 普通索引名則為 idx_欄位名。
說明: pk_ 即 primary key; uk_ 即 unique key; idx_ 即 index 的簡稱。
6. 【強制】小數型別為 decimal,禁止使用 float 和 double。
說明: float 和 double 在儲存的時候,存在精度損失的問題,很可能在值的比較時,得到不
正確的結果。如果儲存的資料範圍超過 decimal
7. 【強制】如果儲存的字串長度幾乎相等,使用 char 定長字串型別。
8. 【強制】 varchar 是可變長字串,不預先分配儲存空間,長度不要超過 5000,如果儲存長
度大於此值,定義欄位型別為 text,獨立出來一張表,用主鍵來對應,避免影響其它欄位索
引效率。
9. 【強制】表必備三欄位: id, gmt_create, gmt_modified。
說明: 其中 id 必為主鍵,型別為 bigint unsigned、單表時自增、步長為 1。 gmt_create,
gmt_modified 的型別均為 datetime 型別,前者現在時表示主動建立,後者過去分詞表示被
動更新。
10. 【推薦】表的命名最好是加上“業務名稱_表的作用”。
正例: alipay_task / force_project / trade_config
11. 【推薦】庫名與應用名稱儘量一致。
12. 【推薦】如果修改欄位含義或對欄位表示的狀態追加時,需要及時更新欄位註釋。
13. 【推薦】欄位允許適當冗餘,以提高查詢效能,但必須考慮資料一致。冗餘欄位應遵循:
1) 不是頻繁修改的欄位。
2) 不是 varchar 超長欄位,更不能是 text 欄位。
正例: 商品類目名稱使用頻率高,欄位長度短,名稱基本一成不變,可在相關聯的表中冗餘存
儲類目名稱,避免關聯查詢。
14. 【推薦】單錶行數超過 500 萬行或者單表容量超過 2GB,才推薦進行分庫分表。
說明: 如果預計三年後的資料量根本達不到這個級別,請不要在建立表時就分庫分表。
15. 【參考】合適的字元儲存長度,不但節約資料庫表空間、節約索引儲存,更重要的是提升檢
索速度。
正例: 如下表,其中無符號值可以避免誤存負數, 且擴大了表示範圍。
人 | 150 歲之內 | tinyint unsigned | 1 | 無符號值: 0 到 255 |
龜 | 數百歲 | smallint unsigned | 2 | 無符號值: 0 到 65535 |
恐龍化石 | 數千萬年 | int unsigned | 4 | 無符號值: 0 到約 42.9 億 |
太陽 | 約 50 億年 | bigint unsigned | 8 | 無符號值: 0 到約 10 的 19 次方 |
(二)索引規約
1. 【強制】業務上具有唯一特性的欄位,即使是多個欄位的組合,也必須建成唯一索引。
說明: 不要以為唯一索引影響了 insert 速度,這個速度損耗可以忽略,但提高查詢速度是明
顯的; 另外,即使在應用層做了非常完善的校驗控制,只要沒有唯一索引,根據墨菲定律,必
然有髒資料產生。
2. 【強制】超過三個表禁止 join。需要 join 的欄位,資料型別必須絕對一致; 多表關聯查詢時,
保證被關聯的欄位需要有索引。
說明: 即使雙表 join 也要注意表索引、 SQL 效能。
3. 【強制】在 varchar 欄位上建立索引時,必須指定索引長度,沒必要對全欄位建立索引,根據
實際文字區分度決定索引長度即可。
說明: 索引的長度與區分度是一對矛盾體,一般對字串型別資料,長度為 20 的索引,區分
度會高達 90%以上,可以使用 count(distinct left(列名, 索引長度))/count(*)的區分度
來確定。
4. 【強制】頁面搜尋嚴禁左模糊或者全模糊,如果需要請走搜尋引擎來解決。
說明: 索引檔案具有 B-Tree 的最左字首匹配特性,如果左邊的值未確定,那麼無法使用此索
引。
5. 【推薦】如果有 order by 的場景,請注意利用索引的有序性。 order by 最後的欄位是組合
索引的一部分,並且放在索引組合順序的最後,避免出現 file_sort 的情況,影響查詢效能。
正例: where a=? and b=? order by c; 索引: a_b_c
反例: 索引中有範圍查詢,那麼索引有序性無法利用,如: WHERE a>10 ORDER BY b; 索引
a_b 無法排序。
6. 【推薦】利用覆蓋索引來進行查詢操作, 避免回表。
說明: 如果一本書需要知道第 11 章是什麼標題,會翻開第 11 章對應的那一頁嗎?目錄瀏覽
一下就好,這個目錄就是起到覆蓋索引的作用。
正例: 能夠建立索引的種類分為主鍵索引、唯一索引、普通索引三種,而覆蓋索引只是一種查
詢的一種效果,用 explain 的結果, extra 列會出現: using index。
7. 【推薦】利用延遲關聯或者子查詢優化超多分頁場景。
說明: MySQL 並不是跳過 offset 行,而是取 offset+N 行,然後返回放棄前 offset 行,返回
N 行,那當 offset 特別大的時候,效率就非常的低下,要麼控制返回的總頁數,要麼對超過
特定閾值的頁數進行 SQL 改寫。
正例: 先快速定位需要獲取的 id 段,然後再關聯:
SELECT a.* FROM 表 1 a, (select id from 表 1 where 條件 LIMIT 100000,20 ) b where a.id=b.id
8. 【推薦】 SQL 效能優化的目標:至少要達到 range 級別, 要求是 ref 級別, 如果可以是 consts
最好。
說明:
1) consts 單表中最多隻有一個匹配行(主鍵或者唯一索引) ,在優化階段即可讀取到資料。
2) ref 指的是使用普通的索引(normal index) 。
3) range 對索引進行範圍檢索。
反例: explain 表的結果, type=index,索引物理檔案全掃描,速度非常慢,這個 index 級
別比較 range 還低,與全表掃描是小巫見大巫。
9. 【推薦】建組合索引的時候,區分度最高的在最左邊。
正例: 如果 where a=? and b=? , 如果 a 列的幾乎接近於唯一值,那麼只需要單建 idx_a
索引即可。
說明: 存在非等號和等號混合時,在建索引時,請把等號條件的列前置。如: where c>? and
d=? 那麼即使 c 的區分度更高,也必須把 d 放在索引的最前列, 即索引 idx_d_c。
10. 【推薦】 防止因欄位型別不同造成的隱式轉換, 導致索引失效。
11. 【參考】建立索引時避免有如下極端誤解:
1) 寧濫勿缺。 認為一個查詢就需要建一個索引。
2) 寧缺勿濫。 認為索引會消耗空間、嚴重拖慢更新和新增速度。
3) 抵制惟一索引。 認為業務的惟一性一律需要在應用層通過“先查後插”方式解決。
(三)SQL 語句
1. 【強制】不要使用 count(列名)或 count(常量)來替代 count(*), count(*)是 SQL92 定義的
標準統計行數的語法,跟資料庫無關,跟 NULL 和非 NULL 無關。
說明: count(*)會統計值為 NULL 的行,而 count(列名)不會統計此列為 NULL 值的行。
2. 【強制】 count(distinct col) 計算該列除 NULL 之外的不重複行數, 注意 count(distinct
col1, col2) 如果其中一列全為 NULL,那麼即使另一列有不同的值,也返回為 0。
3. 【強制】當某一列的值全是 NULL 時, count(col)的返回結果為 0,但 sum(col)的返回結果為
NULL,因此使用 sum()時需注意 NPE 問題。
正例: 可以使用如下方式來避免 sum 的 NPE 問題: SELECT IF(ISNULL(SUM(g)),0,SUM(g))
FROM table;
4. 【強制】使用 ISNULL()來判斷是否為 NULL 值。
說明: NULL 與任何值的直接比較都為 NULL。
1) NULL<>NULL 的返回結果是 NULL, 而不是 false。
2) NULL=NULL 的返回結果是 NULL, 而不是 true。
3) NULL<>1 的返回結果是 NULL,而不是 true。
5. 【強制】 在程式碼中寫分頁查詢邏輯時,若 count 為 0 應直接返回,避免執行後面的分頁語句。
6. 【強制】不得使用外來鍵與級聯,一切外來鍵概念必須在應用層解決。
說明: 以學生和成績的關係為例, 學生表中的 student_id 是主鍵,那麼成績表中的 student_id
則為外來鍵。如果更新學生表中的 student_id,同時觸發成績表中的 student_id 更新, 即為
級聯更新。外來鍵與級聯更新適用於單機低併發,不適合分散式、高併發叢集; 級聯更新是強阻
塞,存在資料庫更新風暴的風險; 外來鍵影響資料庫的插入速度。
7. 【強制】禁止使用儲存過程,儲存過程難以除錯和擴充套件,更沒有移植性。
8. 【強制】資料訂正(特別是刪除、 修改記錄操作) 時,要先 select,避免出現誤刪除,確認
無誤才能執行更新語句。
9. 【推薦】 in 操作能避免則避免,若實在避免不了,需要仔細評估 in 後邊的集合元素數量,控
制在 1000 個之內。
10. 【參考】 如果有國際化需要,所有的字元儲存與表示,均以 utf-8 編碼,注意字元統計函式
的區別。
說明:
SELECT LENGTH("輕鬆工作"); 返回為 12
SELECT CHARACTER_LENGTH("輕鬆工作"); 返回為 4
如果需要儲存表情,那麼選擇 utf8mb4 來進行儲存,注意它與 utf-8 編碼的區別。
11. 【參考】 TRUNCATE TABLE 比 DELETE 速度快,且使用的系統和事務日誌資源少,但 TRUNCATE
無事務且不觸發 trigger,有可能造成事故,故不建議在開發程式碼中使用此語句。
說明: TRUNCATE TABLE 在功能上與不帶 WHERE 子句的 DELETE 語句相同。
(四)ORM 對映
1. 【強制】在表查詢中,一律不要使用 * 作為查詢的欄位列表,需要哪些欄位必須明確寫明。說明: 1) 增加查詢分析器解析成本。 2) 增減欄位容易與 resultMap 配置不一致。 3)無用字
段增加網路消耗,尤其是 text 型別的欄位。
2. 【強制】 POJO 類的布林屬性不能加 is,而資料庫欄位必須加 is_,要求在 resultMap 中進行
欄位與屬性之間的對映。
說明: 參見定義 POJO 類以及資料庫欄位定義規定,在<resultMap>中增加對映,是必須的。
在 MyBatis Generator 生成的程式碼中,需要進行對應的修改。
3. 【強制】不要用 resultClass 當返回引數,即使所有類屬性名與資料庫欄位一一對應,也需
要定義; 反過來,每一個表也必然有一個 POJO 類與之對應。
說明: 配置對映關係,使欄位與 DO 類解耦,方便維護。
4. 【強制】 sql.xml 配置引數使用: #{}, #param# 不要使用${} 此種方式容易出現 SQL 注入。
5. 【強制】 iBATIS 自帶的 queryForList(String statementName,
相關推薦
阿里java開發規範(6)---MySQL資料庫
五、 MySQL 資料庫(一)建表規約1. 【強制】表達是與否概念的欄位,必須使用 is_xxx 的方式命名,資料型別是 unsigned tinyint( 1 表示是, 0 表示否)。說明: 任何欄位如果為非負數,必須是 unsigned。注意: POJO 類中的任何布林型
Java開發規範(一)
本文摘自阿里開發規範,是阿里工程師們嚴格遵循的開發標準,同時也是培養自己寫出高質量程式碼的必然要求,不讓自己寫出來的程式碼像個剛畢業的。 1、命名的風格:1. 程式碼中的命名均不能以下劃線或美元符號開始,也不能以下劃線或美元符號結束。 反例: _name $name2.
阿里巴巴 Java 開發手冊(筆記)
【命名規約】 抽象類命名使用Abstract或者Base開頭 測試類名使用Test結尾 如果使用到了設計模式,在類名中體現具體的模式 OrderFactory LonginProxy 【常量定義】 long型別的初始賦值必須使用大寫的L 使用專門的類來維護常量ConfigC
java===java基礎學習(6)---流程控制,for,if,switch,continue,break
nbsp int exception pub ase nio 內部 註意點 多重循環 註意點: for循環的用法和python截然不同,註意格式 switch~,switch對應的case每當執行完畢都要break,由於基本不怎麽用switch,所以作為了解。 中斷流程
數據庫之mysql篇(6)—— mysql常用函數函數/自定義函數
多個 color 9.png 方法 定義 gpo 類型 好的 個數 常用函數 運算函數 我相信你都能看懂,所以以上的不再做過多解釋 然後還有個,前面漏掉的between and: 意指10是否在0到20之間,如果
windows環境下搭建Java開發環境(一):jdk安裝和配置
變量 win jns jdk安裝 分享 tool 直接 www. 技術 一、資源下載 官網:http://www.oracle.com/technetwork/java/javase/downloads/index.html 本人安裝的是jdk1.8,百度雲資源:鏈
Java並發(6)- CountDownLatch、Semaphore與AQS
退出 很好 不同的 釋放 pri bcd EDA 大型 pro 引言 上一篇文章中詳細分析了基於AQS的ReentrantLock原理,ReentrantLock通過AQS中的state變量0和1之間的轉換代表了獨占鎖。那麽可以思考一下,當state變量大於1時代表了什麽?
Java開發筆記(二)Java工程的帝國區劃
頂部 圖片 最有 屬於 聚集地 合格 ext info 主界面 上一篇文章介紹了如何運行了第一個Java程序“Hello World”。然而這個開發環境看起來那麽陌生,一個個名字符號完全不知道它們是幹啥的呀,對於初學者來說,好比天書一般,多看幾眼感覺都要走火入魔了。因此接下
Java開發筆記(四)Java帝國的度量衡
時間 我們 true 都是 不難 class 右鍵菜單 imp 既然 秦始皇統一中國之後,實行“書同文,車同軌”,把貨幣和各種度量衡都統一起來,從而締造了一個秩序井然的帝國。既然統一度量衡是每個帝國都要做的事情,Java帝國也不例外,對於人生地不熟的初學者來說,只有認識了J
Java開發筆記(六)特殊數字的表達
world 表達 int 數據 decimal stat java語言 細節 進制數 之前的文章提到,Java語言不但支持大眾熟知的十進制數,也支持計算機特有的二進制數、八進制數和十六進制數。可是在給數值變量賦值的時候,等號右邊的數字明顯屬於十進制,那究竟要如何書寫其它進制
Java開發筆記(九)賦值運算符及其演化
運行 加減 pre 存在 運算 而在 否則 四則運算 out 前面的加減乘除四則運算,計算結果通過等號輸出給指定變量,註意此時代碼把變量放到等號左邊。而在算術課本裏,加法運算的完整寫法類似於“1+1=2”這樣,運算結果應該跟在等號右邊。不過代數課本裏的方程式存在“x=y+1
「深入Java虛擬機(6)」:Java語法糖
拆裝箱 重載 jdk1 支持 名稱 不存在 語法糖 pub 簽名 語法糖(Syntactic Sugar),也稱糖衣語法,是由英國計算機學家Peter.J.Landin發明的一個術語,指在計算機語言中添加的某種語法,這種語法對語言的功能並沒有影響,但是更方便程序員使用。Ja
Java開發筆記(五)數值變數的型別
如今個人電腦的配置越來越高,記憶體和硬碟的容量大小都是以G為單位,而1G=1024M=10241024K=102410241024位元組。不過在PC的早期發展階段,電腦的儲存空間卻是十分有限的,像2000年前後廣泛使用的3.5寸軟盤,其儲存容量只有區區1.44M,當時流行的SDR記憶體容
Java開發筆記(十)一元運算子的技巧
前面講到賦值運算子的時候,提到“x = x+7”可以被“x += 7”所取代,當然Java程式設計中給某個變數自加7並不常見,常見的是給某變數自加1,就像走臺階,一般都是一級一級臺階地走,犯不著一下子跳上七級臺階。那麼對於變數自加1的情況,既可以寫成“x = x+1”,也可以寫成“x +
Java併發程式設計(6):Runnable和Thread實現多執行緒的區別(含程式碼)
Java中實現多執行緒有兩種方法:繼承Thread類、實現Runnable介面,在程式開發中只要是多執行緒,肯定永遠以實現Runnable介面為主,因為實現Runnable介面相比繼承Thread類有如下優勢: 1、可以避免由於Java的單繼承特性而帶來的侷限; 2、增強程式的健壯性,程式碼能夠被多個執行
Java併發程式設計(6)- J.U.C元件拓展
J.U.C-FutureTask 在Java中一般通過繼承Thread類或者實現Runnable介面這兩種方式來建立執行緒,但是這兩種方式都有個缺陷,就是不能在執行完成後獲取執行的結果,因此Java 1.5之後提供了Callable和Future介面,通過它們就可以在任務執行完畢之後得到任務的執行結果。
Java開發筆記(序)章節目錄
現將本部落格的Java學習文章整理成以下筆記目錄,方便查閱。 第一章 初識JavaJava開發筆記(一)第一個Java程式Java開發筆記(二)Java工程的帝國區劃Java開發筆記(三)Java帝國的特種官吏Java開發筆記(四)Java帝國的度量衡 第二章 數值變數Java開發筆記(五)數值變數的型別
「深入Java虛擬機器(6)」:Java語法糖
語法糖(Syntactic Sugar),也稱糖衣語法,是由英國計算機學家Peter.J.Landin發明的一個術語,指在計算機語言中新增的某種語法,這種語法對語言的功能並沒有影響,但是更方便程式設計師使用。Java中最常用的語法糖主要有泛型、變長引數、條件編譯、自動拆裝箱、內部類等。虛擬機器並不支援這些語法
JAVA高階基礎(6)---Vector和LinkedList
Vector 是 List 介面一個長度可變的陣列的實現。 可以儲存null 是同步的(是執行緒安全的) 注:更多詳細方法請自行在 API 上查詢 ArrayList和Vector的區別:是否是同步的 package or
Java程式設計思想(6)
第19章 列舉型別 1 enum的函式,ordinal()返回enum的int值,name()返回enum的值 enum Shrubbery {GROUND,CRAWLING,HANGING} public class TwoTuple{ public static void mai