一:建表規(guī)約
1.【強(qiáng)制】表達(dá)是與否概念的字段,必須使用is_xxx的方式命名孩等,數(shù)據(jù)類型是unsigned tinyint(1表示是涉馅,0表示否)旭蠕,此規(guī)則同樣適用于odps建表。
說明:任何字段如果為非負(fù)數(shù)亭枷,必須是unsigned袭艺。
2.【強(qiáng)制】表名、字段名必須使用小寫字母或數(shù)字叨粘;禁止出現(xiàn)數(shù)字開頭猾编,禁止兩個(gè)下劃線中間只 出現(xiàn)數(shù)字。數(shù)據(jù)庫字段名的修改代價(jià)很大升敲,因?yàn)闊o法進(jìn)行預(yù)發(fā)布袍镀,所以字段名稱需要慎重考慮。
正例:getter_admin冻晤,task_config,level3_name
反例:GetterAdmin绸吸,taskConfig鼻弧,level_3_name
3.【強(qiáng)制】表名不使用復(fù)數(shù)名詞。
說明:表名應(yīng)該僅僅表示表里面的實(shí)體內(nèi)容锦茁,不應(yīng)該表示實(shí)體數(shù)量攘轩,對(duì)應(yīng)于DO類名也是單數(shù)
形式,符合表達(dá)習(xí)慣码俩。
4.【強(qiáng)制】禁用保留字度帮,如desc、range稿存、match笨篷、delayed等,參考官方保留字瓣履。
5.【強(qiáng)制】唯一索引名為uk_字段名率翅;普通索引名則為idx_字段名。 說明:uk_即unique key袖迎;idx_即index的簡(jiǎn)稱冕臭。
6.【強(qiáng)制】小數(shù)類型為decimal,禁止使用float和double燕锥。
說明:float和double在存儲(chǔ)的時(shí)候辜贵,存在精度損失的問題,很可能在值的比較時(shí)归形,得到不
正確的結(jié)果托慨。如果存儲(chǔ)的數(shù)據(jù)范圍超過decimal的范圍,建議將數(shù)據(jù)拆成整數(shù)和小數(shù)分開存儲(chǔ)暇榴。
7.【強(qiáng)制】如果存儲(chǔ)的字符串長(zhǎng)度幾乎相等榴芳,使用CHAR定長(zhǎng)字符串類型嗡靡。
8.【強(qiáng)制】varchar是可變長(zhǎng)字符串,不預(yù)先分配存儲(chǔ)空間窟感,長(zhǎng)度不要超過5000讨彼,如果存儲(chǔ)長(zhǎng)度
大于此值,定義字段類型為TEXT柿祈,獨(dú)立出來一張表哈误,用主鍵來對(duì)應(yīng),避免影響其它字段索引
效率躏嚎。
9.【強(qiáng)制】表必備三字段:id, gmt_create, gmt_modified蜜自。 說明:其中id必為主鍵,類型為unsigned bigint卢佣、單表時(shí)自增重荠、步長(zhǎng)為1;分表時(shí)改為從
TDDL Sequence取值虚茶,確保分表之間的全局唯一戈鲁。gmt_create, gmt_modified的類型均為
date_time類型。
10.【推薦】表的命名最好是加上“業(yè)務(wù)名稱_表的作用”嘹叫,避免上云梯后婆殿,再與其它業(yè)務(wù)表關(guān)聯(lián)
時(shí)有混淆。
正例:tiger_task / tiger_reader / mpp_config
11.【推薦】庫名與應(yīng)用名稱盡量一致罩扇。
12.【推薦】如果修改字段含義或?qū)ψ侄伪硎镜臓顟B(tài)追加時(shí)婆芦,需要及時(shí)更新字段注釋。
13.【推薦】字段允許適當(dāng)冗余喂饥,以提高性能消约,但是必須考慮數(shù)據(jù)同步的情況。冗余字段應(yīng)遵循:
1)不是頻繁修改的字段员帮。
2)不是varchar超長(zhǎng)字段荆陆,更不能是text字段。
正例:各業(yè)務(wù)線經(jīng)常冗余存儲(chǔ)商品名稱集侯,避免查詢時(shí)需要調(diào)用IC服務(wù)獲取被啼。
14.【推薦】單表行數(shù)超過500萬行或者單表容量超過2GB,才推薦進(jìn)行分庫分表棠枉。
說明:如果預(yù)計(jì)三年后的數(shù)據(jù)量根本達(dá)不到這個(gè)級(jí)別浓体,請(qǐng)不要在創(chuàng)建表時(shí)就分庫分表。
反例:某業(yè)務(wù)三年總數(shù)據(jù)量才2萬行辈讶,卻分成1024張表命浴,問:你為什么這么設(shè)計(jì)?答:分1024
張表,不是標(biāo)配嗎生闲?
15.【參考】合適的字符存儲(chǔ)長(zhǎng)度媳溺,不但節(jié)約數(shù)據(jù)庫表空間、節(jié)約索引存儲(chǔ)碍讯,更重要的是提升檢索
速度悬蔽。
正例:人的年齡用unsigned tinyint(表示范圍0-255,人的壽命不會(huì)超過255歲)捉兴;海龜就
必須是smallint蝎困,但如果是太陽的年齡,就必須是int倍啥;如果是所有恒星的年齡都加起來禾乘,那
么就必須使用bigint。
二:索引規(guī)約
1.【強(qiáng)制】業(yè)務(wù)上具有唯一特性的字段虽缕,即使是組合字段始藕,也必須建成唯一索引。 說明:不要以為唯一索引影響了insert速度氮趋,這個(gè)速度損耗可以忽略伍派,但提高查找速度是明
顯的;另外凭峡,即使在應(yīng)用層做了非常完善的校驗(yàn)和控制,只要沒有唯一索引决记,根據(jù)墨菲定律摧冀,
必然有臟數(shù)據(jù)產(chǎn)生。
2.【強(qiáng)制】超過三個(gè)表禁止join系宫。需要join的字段索昂,數(shù)據(jù)類型保持絕對(duì)一致;多表關(guān)聯(lián)查詢時(shí)扩借, 保證被關(guān)聯(lián)的字段需要有索引椒惨。
說明:即使雙表join也要注意表索引、SQL性能潮罪。
3.【強(qiáng)制】在varchar字段上建立索引時(shí)康谆,必須指定索引長(zhǎng)度,沒必要對(duì)全字段建立索引嫉到,根據(jù)
實(shí)際文本區(qū)分度決定索引長(zhǎng)度沃暗。
說明:索引的長(zhǎng)度與區(qū)分度是一對(duì)矛盾體,一般對(duì)字符串類型數(shù)據(jù)何恶,長(zhǎng)度為20的索引孽锥,區(qū)分
度會(huì)高達(dá)90%以上,可以使用count(distinct left(列名,索引長(zhǎng)度))/count(*)的區(qū)分度來
確定。
4.【強(qiáng)制】頁面搜索嚴(yán)禁左模糊或者全模糊惜辑,如果需要請(qǐng)走搜索引擎來解決唬涧。
說明:索引文件具有B-Tree的最左前綴匹配特性,如果左邊的值未確定盛撑,那么無法使用此索
引碎节。
5.【推薦】如果有order by的場(chǎng)景,請(qǐng)注意利用索引的有序性撵彻。order by最后的字段是組合索 引的一部分钓株,并且放在索引組合順序的最后,避免出現(xiàn)file_sort的情況陌僵,影響查詢性能轴合。
正例:where a=? and b=? order by c;索引:a_b_c
反例:索引中有范圍查找,那么索引有序性無法利用碗短,如:WHERE a>10 ORDER BY b;索引a_b
無法排序受葛。
6.【推薦】利用覆蓋索引來進(jìn)行查詢操作,來避免回表操作偎谁。
說明:如果一本書需要知道第11章是什么標(biāo)題总滩,會(huì)翻開第11章對(duì)應(yīng)的那一頁嗎?目錄瀏覽一
下就好巡雨,這個(gè)目錄就是起到覆蓋索引的作用闰渔。
正例:IDB能夠建立索引的種類:主鍵索引、唯一索引铐望、普通索引冈涧,而覆蓋索引是一種查詢的
一種效果,用explain的結(jié)果正蛙,extra列會(huì)出現(xiàn):using index.
7.【推薦】利用延遲關(guān)聯(lián)或者子查詢優(yōu)化超多分頁場(chǎng)景督弓。 說明:MySQL并不是跳過offset行,而是取offset+N行乒验,然后返回放棄前offset行愚隧,返回N
行,那當(dāng)offset特別大的時(shí)候锻全,效率就非常的低下狂塘,要么控制返回的總頁數(shù),要么對(duì)超過特
定閾值的頁數(shù)進(jìn)行SQL改寫鳄厌。
正例:先快速定位需要獲取的id段睹耐,然后再關(guān)聯(lián):SELECT a.* FROM表1 a, (select id from表1 where條件LIMIT 100000,20 ) b where a.id=b.id
8.【推薦】SQL性能優(yōu)化的目標(biāo):至少要達(dá)到range級(jí)別,要求是ref級(jí)別部翘,如果可以是consts最好硝训。
說明:
1)consts單表中最多只有一個(gè)匹配行(主鍵或者唯一索引),在優(yōu)化階段即可讀取到數(shù)據(jù)。
2)ref指的是使用普通的索引窖梁。(normal index)
3)range對(duì)索引進(jìn)范圍檢索赘风。
反例:explain表的結(jié)果,type=index纵刘,索引物理文件全掃描邀窃,速度非常慢,這個(gè)index級(jí)別
比較range還低假哎,與全表掃描是小巫見大巫瞬捕。
9.【推薦】建組合索引的時(shí)候,區(qū)分度最高的在最左邊舵抹。 正例:如果where a=? and b=?肪虎,a列的幾乎接近于唯一值,那么只需要單建idx_a索引即可惧蛹。
說明:存在非等號(hào)和等號(hào)混合判斷條件時(shí)扇救,在建索引時(shí),請(qǐng)把等號(hào)條件的列前置香嗓。如:where a>?
and b=?那么即使a的區(qū)分度更高迅腔,也必須把b放在索引的最前列。
10.【參考】創(chuàng)建索引時(shí)避免有如下極端誤解:
1)誤認(rèn)為一個(gè)查詢就需要建一個(gè)索引靠娱。
2)誤認(rèn)為索引會(huì)消耗空間沧烈、嚴(yán)重拖慢更新和新增速度。
3)誤認(rèn)為唯一索引一律需要在應(yīng)用層通過“先查后插”方式解決像云。
三: SQL規(guī)約
1.【強(qiáng)制】不要使用count(列名)或count(常量)來替代count(*)锌雀,count(*)就是SQL92定義的 標(biāo)準(zhǔn)統(tǒng)計(jì)行數(shù)的語法,跟數(shù)據(jù)庫無關(guān)苫费,跟NULL和非NULL無關(guān)汤锨。
說明:count(*)會(huì)統(tǒng)計(jì)值為NULL的行双抽,而count(列名)不會(huì)統(tǒng)計(jì)此列為NULL值的行百框。
2.【強(qiáng)制】count(distinct col)計(jì)算該列除NULL之外的不重復(fù)數(shù)量。注意count(distinct col1, col2)如果其中一列全為NULL牍汹,那么即使另一列有不同的值铐维,也返回為0。
3.【強(qiáng)制】當(dāng)某一列的值全是NULL時(shí)慎菲,count(col)的返回結(jié)果為0嫁蛇,但sum(col)的返回結(jié)果為NULL,因此使用sum()時(shí)需注意NPE問題露该。
正例:可以使用如下方式來避免sum的NPE問題:SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM
table;
4.【強(qiáng)制】使用ISNULL()來判斷是否為NULL值睬棚。注意:NULL與任何值的直接比較都為NULL。
說明:
1)NULL<>NULL的返回結(jié)果是NULL,不是false抑党。
2)NULL=NULL的返回結(jié)果是NULL包警,不是true。
3)NULL<>1的返回結(jié)果是NULL底靠,而不是true害晦。
5.【強(qiáng)制】在代碼中寫分頁查詢邏輯時(shí),若count為0應(yīng)直接返回暑中,避免執(zhí)行后面的分頁語句壹瘟。
6.【強(qiáng)制】不得使用外鍵與級(jí)聯(lián),一切外鍵概念必須在應(yīng)用層解決鳄逾。 說明:(概念解釋)學(xué)生表中的student_id是主鍵稻轨,那么成績(jī)表中的student_id則為外鍵。
如果更新學(xué)生表中的student_id严衬,同時(shí)觸發(fā)成績(jī)表中的student_id更新澄者,則為級(jí)聯(lián)更新。外
鍵與級(jí)聯(lián)更新適用于單機(jī)低并發(fā)请琳,不適合分布式粱挡、高并發(fā)集群;級(jí)聯(lián)更新是強(qiáng)阻塞俄精,存在數(shù)據(jù)
庫更新風(fēng)暴的風(fēng)險(xiǎn)询筏;外鍵影響數(shù)據(jù)庫的插入速度。
7.【強(qiáng)制】禁止使用存儲(chǔ)過程竖慧,存儲(chǔ)過程難以調(diào)試和擴(kuò)展嫌套,更沒有移植性。
8.【強(qiáng)制】IDB數(shù)據(jù)訂正時(shí)圾旨,刪除和修改記錄時(shí)踱讨,要先select,避免出現(xiàn)誤刪除砍的,確認(rèn)無誤才能 提交執(zhí)行痹筛。
9.【推薦】in操作能避免則避免,若實(shí)在避免不了廓鞠,需要仔細(xì)評(píng)估in后邊的集合元素?cái)?shù)量帚稠,控 制在1000個(gè)之內(nèi)。
10.【參考】因阿里巴巴全球化需要床佳,所有的字符存儲(chǔ)與表示滋早,均以u(píng)tf-8編碼,那么字符計(jì)數(shù)方
法注意:
說明:
SELECT LENGTH("阿里巴巴")砌们; 返回為12
SELECT CHARACTER_LENGTH("阿里巴巴")杆麸; 返回為4
如果要使用表情搁进,那么使用utfmb4來進(jìn)行存儲(chǔ),注意它與utf-8編碼昔头。
11.【參考】TRUNCATE TABLE比DELETE速度快拷获,且使用的系統(tǒng)和事務(wù)日志資源少,但TRUNCATE
無事務(wù)且不觸發(fā)trigger减细,有可能造成事故匆瓜,故不建議在開發(fā)代碼中使用此語句。
說明:TRUNCATE TABLE在功能上與不帶WHERE子句的DELETE語句相同未蝌。