MySQL 相關(guān)規(guī)范

流程規(guī)范

流程圖.jpg
  1. 服務正式上線前,一定要check下線上數(shù)據(jù)庫改動已經(jīng)上線。不然會引起線上事故!
  2. 測試環(huán)境也要有,不然測試環(huán)境后面會越來越難建設。

設計規(guī)范

規(guī)范共分為【強制】、【推薦】、【參考】三個等級,優(yōu)先級從高至低,如違反【強制】規(guī)范Reviewer應當打回。

命名規(guī)范

【強制】表的命名最好是“業(yè)務名稱_表的作用” ,無需額外的數(shù)據(jù)庫名開頭。

對于bits數(shù)據(jù)庫來說,正例:app_build_config,workflow_job; 反例:bits_app_info,bits_xxx;

【強制】表名、字段名必須使用小寫字母或****數(shù)字,禁止出現(xiàn)數(shù)字開頭,禁止兩個下劃線中間只 出現(xiàn)數(shù)字。正例:app_user,app_config,level3_name 反例:AppUser,rdcConfig,level_3_name

【強制】表名使用單數(shù)。 說明:表名應該僅僅表示表里面的實體內(nèi)容,不應該表示實體數(shù)量,符合表達習慣。

【強制】索引名字的前綴必須idx_,唯一約束/索引的前綴必須uk_

【強制】所有命名必須使用全名,有默認約定的除外,如果超過 30 個字符,使用縮寫

【強制】每個字段和表必須提供清晰的注釋,現(xiàn)在沒有注釋 rds 不讓建表。


【推薦】庫的命名最好是“系統(tǒng)名稱_子系統(tǒng)名”, 正例 bits_pipeline,bits_ttp。

字段規(guī)范

【強制】必加的三個字段

  • id(unsigned bigint),單表時自增。防止枚舉時用id generator生成
  • create_time(timestamp),用于記錄主動創(chuàng)建時間,默認值:current_timestamp
  • update_time(timestamp),用于記錄最后更新時間,默認值: current_timestamp

【強制】每個表不超過30個字段

【強制】如果存儲的字符串長度固定,使用 char 定長字符串類型

【強制】文本數(shù)據(jù)盡量用varchar ,變長存儲,更省存儲空間,長度不要超過 2700,如果存儲長 度大于此值,定義字段類型為 text,獨立出來一張表,用主鍵來對應,避免影響其它字段索引效率。

【強制】存儲字段如果為非負數(shù),默認加上UNSIGNED。

【強制】小數(shù)類型為 decimal,禁止使用 float 和 double。decimal不存在精度損失,數(shù)據(jù)類型decimal(p,s) 需要分別指定小數(shù)的最大位數(shù)(p)和小數(shù)位的數(shù)量(s)。

【強制】如果修改字段含義或?qū)ψ侄伪硎镜臓顟B(tài)追加時,需要及時更新字段注釋。

【強制】業(yè)務中選擇性很少的狀態(tài)、****類型 等字段推薦使用 TINYINT。從1開始枚舉,并且將具體含義寫在字段備注里。禁止使用 bool 來存狀態(tài)。

【強制】索引字段不要設置為null

【強制】優(yōu)先選擇utf8mb4字符集,它的兼容性最好,而且還支持emoji字符。


【推薦】json 的數(shù)據(jù)使用 json 類型存儲而不是 text。MySQL 會幫我們做 json 格式校驗。注意長度限制。(看業(yè)務場景)


【推薦】字段盡量設置為 NOT NULL, 為字段提供默認值。 如字符型的默認值為一個空字符串值;數(shù)值型默認值為數(shù)值 0;邏輯型的默認值為數(shù)值 0;

【推薦】考慮業(yè)務場景,選擇軟硬刪除,必要的話,新增 delete_at,軟刪除。

ToDo:補 GORM 和 build Tools @劉思齊 @劉濤

注意點:

  • count(*) 會統(tǒng)計NULL的行, count(列名) 不會統(tǒng)計此列為NULL值的行

  • count(distinct col) 計算該列除 NULL 之外的不重復行數(shù),注意 count(distinct col1, col2) 如果其中一列全為 NULL,那么即使另一列有不同的值,也返回為 0。

【推薦】遇到BLOB、TEXT字段,則盡量拆出去,再用主鍵做關(guān)聯(lián)。超過4k大值拆出,考慮換存儲方案,主從延遲風險。

【推薦】反范式設計:字段允許適當冗余,以提高查詢性能。 如app表中的應用名稱/應用id等唯一鍵,可以在別的業(yè)務表中均存儲一份,避免使用 join。

【推薦】時間類型采用為 timestamp 數(shù)據(jù)類型,因為 datetime 占用 8 字節(jié),timestamp 僅占用4字節(jié),范圍為 1970-01-01 00:00:012038-01-01 00:00:00


【參考】合適的字符存儲長度,不但節(jié)約數(shù)據(jù)庫表空間、節(jié)約索引存儲,更重要的是提升檢索速度。

類型(同義詞) 存儲長度(BYTES) 最小值(SIGNED/UNSIGNED) 最大值(SIGNED/UNSIGNED)
整型數(shù)字
TINYINT 1 -128/0 127/255
SMALLINT 2 -32,768/0 32767/65,535
MEDIUMINT 3 -8,388,608/0 8388607/16,777,215/
INT(INTEGER) 4 -2,14,7483,648/0 2147483647/4,294,967,295/
BIGINT 8 -2^63/0 263-1/264-1
時間類型
DATETIME 8 1001-01-01 00:00:00 9999-12-31 23:59:59
DATE 3 1001-01-01 9999-12-31
TIME 3 00:00:00 23:59:59
YEAR 1 1001 9999
TIMESTAMP 4 1970-01-01 00:00:00 2038-01-01 00:00:00

索引規(guī)范

【強制】表寫多讀少建議索引數(shù)不超過5個。表讀多寫少索引數(shù)不超過10個

【強制】業(yè)務上具有唯一特性的字段,即使是多個字段的組合,也必須建成唯一索引。

【強制】建議不使用 join。如果一定要使用,最多兩個表 join。需要 join 的字段,數(shù)據(jù)類型必須絕對一致;多表關(guān)聯(lián)查詢時, 保證被關(guān)聯(lián)的字段需要有索引。

【強制】在 varchar 字段上建立索引時,必須指定索引長度,沒必要對全字段建立索引,根據(jù) 實際文本區(qū)分度決定索引長度即可。 說明:索引的長度與區(qū)分度是一對矛盾體,一般對字符串類型數(shù)據(jù),長度為 20 的索引,區(qū)分度會高達 90%以上。

【強制】在建立索引時,多考慮建立聯(lián)合索引,并把區(qū)分度最高的字段放在最前面。

【強制】模糊查詢僅允許右模糊 即“xxx%”,如果需要請走ES來解決。

【強制】不要用外鍵,一切外鍵概念在應用層解決。


【推薦】利用覆蓋索引來進行查詢操作,避免回表。即 select b from tableA where a = 1

【推薦】如果選擇性超過 20%(區(qū)分度低于20%),那么全表掃描比使用索引性能更優(yōu),即沒有設置索引的必要。

【推薦】防止因字段類型不同造成的隱式轉(zhuǎn)換,導致索引失效。

【推薦】如果有 order by 的場景,請注意利用索引的有序性。order by 最后的字段是組合索引的一部分,并且放在索引組合順序的最后,避免出現(xiàn) file_sort 的情況,影響查詢性能。

【推薦】不要對頻繁更新字段加索引


【參考】創(chuàng)建索引時避免有如下極端誤解

  • 錯誤一:寧濫勿缺。認為一個查詢就需要建一個索引。

  • 錯誤二:寧缺勿濫。認為索引會消耗空間、嚴重拖慢更新和新增速度。

  • 錯誤三:抵制惟一索引。認為業(yè)務的惟一性一律需要在應用層通過“先查后插”方式解決。

使用規(guī)范

【強制】用Explain來做SQL 性能優(yōu)化,type 至少要達到 range 級別,要求是 ref 級別,如果可以是 consts 最好

描述
system The table has only one row (= system table). This is a special case of the const join type.
const The table has at most one matching row, which is read at the start of the query. Because there is only one row, values from the column in this row can be regarded as constants by the rest of the optimizer. const tables are very fast because they are read only once.
eq_ref One row is read from this table for each combination of rows from the previous tables. Other than the system and const types, this is the best possible join type. It is used when all parts of an index are used by the join and the index is a PRIMARY KEY or UNIQUE NOT NULL index.
ref All rows with matching index values are read from this table for each combination of rows from the previous tables. ref is used if the join uses only a leftmost prefix of the key or if the key is not a PRIMARY KEY or UNIQUE index (in other words, if the join cannot select a single row based on the key value). If the key that is used matches only a few rows, this is a good join type.
fulltext The join is performed using a FULLTEXT index.
ref_or_null This join type is like ref, but with the addition that MySQL does an extra search for rows that contain NULL values. This join type optimization is used most often in resolving subqueries. In the following examples, MySQL can use a ref_or_null join to process ref_table:
index_merge This join type indicates that the Index Merge optimization is used. In this case, the key column in the output row contains a list of indexes used, and key_len contains a list of the longest key parts for the indexes used
unique_subquery This type replaces eq_ref for some IN subqueries of the following form:
index_subquery This join type is similar to unique_subquery. It replaces IN subqueries, but it works for nonunique indexes in subqueries of the following form
range Only rows that are in a given range are retrieved, using an index to select the rows. The key column in the output row indicates which index is used. The key_len contains the longest key part that was used. The ref column is NULL for this type.
index The index join type is the same as ALL, except that the index tree is scanned. This occurs two ways:
- If the index is a covering index for the queries and can be used to satisfy all data required from the table, only the index tree is scanned. In this case, the Extra column says Using index. An index-only scan usually is faster than ALL because the size of the index usually is smaller than the table data.
-A full table scan is performed using reads from the index to look up data rows in index order. Uses index does not appear in the Extra column.
-MySQL can use this join type when the query uses only columns that are part of a single index.
ALL A full table scan is done for each combination of rows from the previous tables. This is normally not good if the table is the first table not marked const, and usually very bad in all other cases. Normally, you can avoid ALL by adding indexes that enable row retrieval from the table based on constant values or column values from earlier tables.

【強制】不要使用 count(列名)或 count(常量)來替代 count(),count()是 SQL92 定義的 標準統(tǒng)計行數(shù)的語法,跟數(shù)據(jù)庫無關(guān),跟 NULL 和非 NULL 無關(guān)。

  • count(*)會統(tǒng)計值為 NULL 的行,而 count(列名)不會統(tǒng)計此列為 NULL 值的行。

【強制】連表查詢的情況下,要確保關(guān)聯(lián)條件的數(shù)據(jù)類型一致,避免嵌套

【強制】使用 ISNULL()來判斷是否為 NULL 值。 說明:NULL 與任何值的直接比較都為 NULL。

  • NULL<>NULL的返回結(jié)果是NULL,而不是false。

  • NULL=NULL的返回結(jié)果是NULL,而不是true。

  • NULL<>1的返回結(jié)果是NULL,而不是true。

【強制】查詢時不要對索引列做計算/使用函數(shù)。避免索引列的類型轉(zhuǎn)換以及字符串編碼轉(zhuǎn)換。

【強制】更新數(shù)據(jù)超過1000條的update,delete和insert語句,需要改成分批量多次更新來進行

【強制】禁止使用存儲過程,視圖,觸發(fā)器,event等高級特性

【強制】in子句中的值不要超過500個

【強制】提RDS DML工單時,update or delete 的長度確定時,加上 limit <行數(shù)>。這樣就算提的工單 DML SQL寫錯了,錯誤造成的影響也可控。(降低工單造成的事故風險)

【強制】提工單的時候備注背景寫一下。


【推薦】不建議使用子查詢,建議將子查詢 SQL 拆開結(jié)合程序多次查詢。

【推薦】不要對索引字段使用負向查詢,比如not in,not like

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • MySQL索引原理 索引目的 索引的目的在于提高查詢效率,可以類比字典,如果要查“mysql”這個單詞,我們肯定需...
    cutieagain閱讀 395評論 0 0
  • Mysql相關(guān) Mysql并發(fā)控制-鎖 共享鎖 共享鎖也稱為讀鎖,讀鎖允許多個連接可以同一時刻并發(fā)的讀取同一資源,...
    萬福來閱讀 333評論 0 0
  • 前言 關(guān)于前面講過的知識點我就不再贅述了,還沒看過的朋友可以進入我的首頁進行查閱(前言部分附贈飛機票)。這篇文章將...
    6曦軒閱讀 620評論 0 0
  • M ysql索引用來快速地尋找那些具有特定值的記錄,所有MySQL索引都以B-樹的形式保存。如果沒有索引,執(zhí)行查詢...
    脆皮雞大蝦閱讀 242評論 0 0
  • 1、幾種主要的數(shù)據(jù)庫引擎的區(qū)別 MyISAM讀取操作速度很快,而且不占用大量的內(nèi)存和存儲資源,但是不支持事務和外鍵...
    小胖六閱讀 575評論 1 2

友情鏈接更多精彩內(nèi)容