MYSQL數(shù)據(jù)庫設(shè)計(jì),查詢規(guī)范

MySQL數(shù)據(jù)庫

(一)建表規(guī)約
1.【強(qiáng)制】表達(dá)是與否概念的字段究反,必須使用is_xxx的方式命名,數(shù)據(jù)類型是unsignedtinyint(1表示是儒洛,0表示否)
精耐。說明:任何字段如果為非負(fù)數(shù),必須是unsigned晶丘。正例:表達(dá)邏輯刪除的字段名is_deleted黍氮,1表示刪除,0表示未刪除浅浮。
2.【強(qiáng)制】表名、字段名必須使用小寫字母或數(shù)字捷枯,禁止出現(xiàn)數(shù)字開頭滚秩,禁止兩個下劃線中間只出現(xiàn)數(shù)字。
數(shù)據(jù)庫字段名的修改代價(jià)很大淮捆,因?yàn)闊o法進(jìn)行預(yù)發(fā)布郁油,所以字段名稱需要慎重考慮。
說明:MySQL在Windows下不區(qū)分大小寫攀痊,但在Linux下默認(rèn)是區(qū)分大小寫桐腌。
因此,數(shù)據(jù)庫名苟径、表名案站、字段名,都不允許出現(xiàn)任何大寫字母棘街,避免節(jié)外生枝蟆盐。
正例:aliyun_admin,rdc_config遭殉,level3_name
反例:AliyunAdmin石挂,rdcConfig,level_3_name
3.【強(qiáng)制】表名不使用復(fù)數(shù)名詞险污。說明:表名應(yīng)該僅僅表示表里面的實(shí)體內(nèi)容痹愚,不應(yīng)該表示實(shí)體數(shù)量,對應(yīng)于DO類名也是單數(shù)形式蛔糯,符合表達(dá)習(xí)慣拯腮。
4.【強(qiáng)制】禁用保留字,如desc渤闷、range疾瓮、match、delayed等飒箭,請參考MySQL官方保留字狼电。
5.【強(qiáng)制】主鍵索引名為pk_字段名蜒灰;唯一索引名為uk_字段名;普通索引名則為idx_字段名肩碟。
說明:pk_ 即primary key强窖;uk_ 即uniquekey;idx_ 即index的簡稱削祈。
6.【強(qiáng)制】小數(shù)類型為decimal翅溺,禁止使用float和double。
說明:float和double在存儲的時候髓抑,存在精度損失的問題咙崎,很可能在值的比較時,得到不正確的結(jié)果吨拍。
如果存儲的數(shù)據(jù)范圍超過decimal的范圍褪猛,建議將數(shù)據(jù)拆成整數(shù)和小數(shù)分開存儲。
7.【強(qiáng)制】如果存儲的字符串長度幾乎相等羹饰,使用char定長字符串類型伊滋。
8.【強(qiáng)制】varchar是可變長字符串,不預(yù)先分配存儲空間队秩,長度不要超過5000笑旺,如果存儲長度大于此值,定義字段類型為text馍资,獨(dú)立出來一張表筒主,用主鍵來對應(yīng),避免影響其它字段索引效率迷帜。
9.【強(qiáng)制】表必備三字段:id, gmt_create, gmt_modified物舒。
說明:其中id必為主鍵,類型為unsigned bigint戏锹、單表時自增冠胯、步長為1。
gmt_create, gmt_modified的類型均為date_time類型锦针,前者現(xiàn)在時表示主動創(chuàng)建荠察,后者過去分詞表示被動更新。
10.【推薦】表的命名最好是加上“業(yè)務(wù)名稱_表的作用”奈搜。正例:alipay_task/ force_project/ trade_config
11.【推薦】庫名與應(yīng)用名稱盡量一致悉盆。
12.【推薦】如果修改字段含義或?qū)ψ侄伪硎镜臓顟B(tài)追加時,需要及時更新字段注釋馋吗。
13.【推薦】字段允許適當(dāng)冗余焕盟,以提高查詢性能,但必須考慮數(shù)據(jù)一致宏粤。
冗余字段應(yīng)遵循:
1)不是頻繁修改的字段脚翘。
2)不是varchar超長字段灼卢,更不能是text字段。
正例:商品類目名稱使用頻率高来农,字段長度短鞋真,名稱基本一成不變,可在相關(guān)聯(lián)的表中冗余存儲類目名稱沃于,避免關(guān)聯(lián)查詢涩咖。
14.【推薦】單表行數(shù)超過500萬行或者單表容量超過2GB,才推薦進(jìn)行分庫分表繁莹。
說明:如果預(yù)計(jì)三年后的數(shù)據(jù)量根本達(dá)不到這個級別檩互,請不要在創(chuàng)建表時就分庫分表。
15.【參考】合適的字符存儲長度咨演,不但節(jié)約數(shù)據(jù)庫表空間盾似、節(jié)約索引存儲,更重要的是提升檢索速度雪标。
正例:如下表,其中無符號值可以避免誤存負(fù)數(shù)溉跃,且擴(kuò)大了表示范圍村刨。
對象年齡區(qū)間類型字節(jié)表示范圍
人150歲之內(nèi)unsigned tinyint1無符號值:0到255
龜數(shù)百歲unsigned smallint2無符號值:0到65535
恐龍化石數(shù)千萬年unsigned int4無符號值:0到約42.9億
太陽約50億年unsigned bigint8無符號值:0到約10的19次方

(二)索引規(guī)約
1.【強(qiáng)制】業(yè)務(wù)上具有唯一特性的字段,即使是多個字段的組合撰茎,也必須建成唯一索引嵌牺。
說明:不要以為唯一索引影響了insert速度,這個速度損耗可以忽略龄糊,但提高查找速度是明顯的逆粹;
另外,即使在應(yīng)用層做了非常完善的校驗(yàn)控制炫惩,只要沒有唯一索引僻弹,根據(jù)墨菲定律,必然有臟數(shù)據(jù)產(chǎn)生他嚷。
2.【強(qiáng)制】超過三個表禁止join蹋绽。需要join的字段,數(shù)據(jù)類型必須絕對一致筋蓖;
多表關(guān)聯(lián)查詢時卸耘,保證被關(guān)聯(lián)的字段需要有索引。說明:即使雙表join也要注意表索引粘咖、SQL性能蚣抗。
3.【強(qiáng)制】在varchar字段上建立索引時,必須指定索引長度瓮下,沒必要對全字段建立索引翰铡,根據(jù)實(shí)際文本區(qū)分度決定索引長度即可钝域。
說明:索引的長度與區(qū)分度是一對矛盾體,一般對字符串類型數(shù)據(jù)两蟀,長度為20的索引网梢,區(qū)分度會高達(dá)90%以上,可以使用count(distinctleft(列名, 索引長度))/count()的區(qū)分度來確定赂毯。
4.【強(qiáng)制】頁面搜索嚴(yán)禁左模糊或者全模糊战虏,如果需要請走搜索引擎來解決。
說明:索引文件具有B-Tree的最左前綴匹配特性党涕,如果左邊的值未確定烦感,那么無法使用此索引。
5.【推薦】如果有orderby的場景膛堤,請注意利用索引的有序性手趣。
orderby最后的字段是組合索引的一部分,并且放在索引組合順序的最后肥荔,避免出現(xiàn)file_sort的情況绿渣,影響查詢性能。
正例:wherea=? andb=? orderbyc;索引:a_b_c
反例:索引中有范圍查找燕耿,那么索引有序性無法利用中符,如:WHEREa>10 ORDERBYb;索引a_b無法排序。
6.【推薦】利用覆蓋索引來進(jìn)行查詢操作誉帅,避免回表淀散。
說明:如果一本書需要知道第11章是什么標(biāo)題,會翻開第11章對應(yīng)的那一頁嗎蚜锨?目錄瀏覽一下就好档插,這個目錄就是起到覆蓋索引的作用。
正例:能夠建立索引的種類:主鍵索引亚再、唯一索引郭膛、普通索引,而覆蓋索引是一種查詢的一種效果针余,用explain的結(jié)果饲鄙,extra列會出現(xiàn):usingindex。
7.【推薦】利用延遲關(guān)聯(lián)或者子查詢優(yōu)化超多分頁場景圆雁。
說明:MySQL并不是跳過offset行忍级,而是取offset+N行,然后返回放棄前offset行伪朽,返回N行轴咱,
那當(dāng)offset特別大的時候,效率就非常的低下,要么控制返回的總頁數(shù)朴肺,要么對超過特定閾值的頁數(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級別戈稿,要求是ref級別西土,如果可以是consts最好。
說明:
1)consts單表中最多只有一個匹配行(主鍵或者唯一索引)鞍盗,在優(yōu)化階段即可讀取到數(shù)據(jù)需了。
2)ref指的是使用普通的索引(normalindex)。
3)range對索引進(jìn)行范圍檢索般甲。
反例:explain表的結(jié)果肋乍,type=index,索引物理文件全掃描敷存,速度非常慢墓造,這個index級別比較range還低,與全表掃描是小巫見大巫锚烦。
9.【推薦】建組合索引的時候觅闽,區(qū)分度最高的在最左邊。正例:如果wherea=? andb=? 涮俄,a列的幾乎接近于唯一值谱煤,那么只需要單建idx_a索引即可。
說明:存在非等號和等號混合判斷條件時禽拔,在建索引時,請把等號條件的列前置室叉。
如:wherea>? andb=? 那么即使a的區(qū)分度更高睹栖,也必須把b放在索引的最前列。
10.【推薦】防止因字段類型不同造成的隱式轉(zhuǎn)換茧痕,導(dǎo)致索引失效野来。
11.【參考】創(chuàng)建索引時避免有如下極端誤解:
1)寧濫勿缺。認(rèn)為一個查詢就需要建一個索引踪旷。
2)寧缺勿濫曼氛。認(rèn)為索引會消耗空間、嚴(yán)重拖慢更新和新增速度令野。
3)抵制惟一索引舀患。認(rèn)為業(yè)務(wù)的惟一性一律需要在應(yīng)用層通過“先查后插”方式解決。

(三)SQL語句
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(*)會統(tǒng)計(jì)值為NULL的行低匙,而count(列名)不會統(tǒng)計(jì)此列為NULL值的行旷痕。
2.【強(qiáng)制】count(distinctcol)計(jì)算該列除NULL之外的不重復(fù)行數(shù),注意count(distinctcol1, col2)如果其中一列全為NULL顽冶,那么即使另一列有不同的值欺抗,也返回為0。
3.【強(qiáng)制】當(dāng)某一列的值全是NULL時强重,count(col)的返回結(jié)果為0绞呈,但sum(col)的返回結(jié)果為NULL,因此使用sum()時需注意NPE問題竿屹。
正例:可以使用如下方式來避免sum的NPE問題:SELECTIF(ISNULL(SUM(g)),0,SUM(g))FROMtable;
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)制】在代碼中寫分頁查詢邏輯時哮缺,若count為0應(yīng)直接返回弄跌,避免執(zhí)行后面的分頁語句。
6.【強(qiáng)制】不得使用外鍵與級聯(lián)尝苇,一切外鍵概念必須在應(yīng)用層解決铛只。
說明:以學(xué)生和成績的關(guān)系為例,學(xué)生表中的student_id是主鍵糠溜,那么成績表中的student_id則為外鍵淳玩。
如果更新學(xué)生表中的student_id,同時觸發(fā)成績表中的student_id更新非竿,即為級聯(lián)更新蜕着。
外鍵與級聯(lián)更新適用于單機(jī)低并發(fā),不適合分布式红柱、高并發(fā)集群承匣;
級聯(lián)更新是強(qiáng)阻塞,存在數(shù)據(jù)庫更新風(fēng)暴的風(fēng)險(xiǎn)锤悄;外鍵影響數(shù)據(jù)庫的插入速度韧骗。
7.【強(qiáng)制】禁止使用存儲過程,存儲過程難以調(diào)試和擴(kuò)展零聚,更沒有移植性宽闲。
8.【強(qiáng)制】數(shù)據(jù)訂正時众眨,刪除和修改記錄時,要先select容诬,避免出現(xiàn)誤刪除娩梨,確認(rèn)無誤才能執(zhí)行更新語句。
9.【推薦】in操作能避免則避免览徒,若實(shí)在避免不了狈定,需要仔細(xì)評估in后邊的集合元素?cái)?shù)量,控制在1000個之內(nèi)习蓬。
10.【參考】如果有全球化需要纽什,所有的字符存儲與表示,均以utf-8編碼躲叼,注意字符統(tǒng)計(jì)函數(shù)的區(qū)別芦缰。
說明:
SELECT LENGTH(“輕松工作”);返回為12
SELECT CHARACTER_LENGTH(“輕松工作”)枫慷;返回為4
如果需要存儲表情让蕾,那么選擇utfmb4來進(jìn)行存儲,注意它與utf-8編碼的區(qū)別或听。
11.【參考】TRUNCATETABLE比DELETE速度快探孝,且使用的系統(tǒng)和事務(wù)日志資源少,
但TRUNCATE無事務(wù)且不觸發(fā)trigger誉裆,有可能造成事故顿颅,故不建議在開發(fā)代碼中使用此語句。
說明:
TRUNCATETABLE在功能上與不帶WHERE子句的DELETE語句相同足丢。

(四)ORM映射
1.【強(qiáng)制】在表查詢中粱腻,一律不要使用* 作為查詢的字段列表,需要哪些字段必須明確寫明斩跌。
說明:
1)增加查詢分析器解析成本栖疑。
2)增減字段容易與resultMap配置不一致。
2.【強(qiáng)制】POJO類的布爾屬性不能加is滔驶,而數(shù)據(jù)庫字段必須加is_,要求在resultMap中進(jìn)行字段與屬性之間的映射卿闹。
說明:參見定義POJO類以及數(shù)據(jù)庫字段定義規(guī)定揭糕,在<resultMap>中增加映射,是必須的锻霎。
在MyBatis Generator生成的代碼中著角,需要進(jìn)行對應(yīng)的修改。
3.【強(qiáng)制】不要用resultClass當(dāng)返回參數(shù)旋恼,即使所有類屬性名與數(shù)據(jù)庫字段一一對應(yīng)吏口,也需要定義;
反過來,每一個表也必然有一個與之對應(yīng)产徊。說明:配置映射關(guān)系昂勒,使字段與DO類解耦,方便維護(hù)舟铜。
4.【強(qiáng)制】sql.xml配置參數(shù)使用:#{}戈盈,#param# 不要使用${} 此種方式容易出現(xiàn)SQL注入。
5.【強(qiáng)制】iBATIS自帶的queryForList(StringstatementName,intstart,intsize)不推薦使用谆刨。
說明:其實(shí)現(xiàn)方式是在數(shù)據(jù)庫取到statementName對應(yīng)的SQL語句的所有記錄塘娶,再通過subList取start,size的子集合。
正例:Map<String, Object> map = new HashMap<String, Object>(); map.put(“start”, start); map.put(“size”, size);
6.【強(qiáng)制】不允許直接拿HashMap與Hashtable作為查詢結(jié)果集的輸出痊夭。
說明:resultClass=”Hashtable”刁岸,會置入字段名和屬性值,但是值的類型不可控她我。
7.【強(qiáng)制】更新數(shù)據(jù)表記錄時虹曙,必須同時更新記錄對應(yīng)的gmt_modified字段值為當(dāng)前時間。
8.【推薦】不要寫一個大而全的數(shù)據(jù)更新接口鸦难。
傳入為POJO類根吁,不管是不是自己的目標(biāo)更新字段,都進(jìn)行update table set c1=value1,c2=value2,c3=value3;
這是不對的合蔽。執(zhí)行SQL時击敌,不要更新無改動的字段,一是易出錯拴事;二是效率低沃斤;三是增加binlog存儲。
9.【參考】@Transactional事務(wù)不要濫用刃宵。事務(wù)會影響數(shù)據(jù)庫的QPS衡瓶,另外使用事務(wù)的地方需要考慮各方面的回滾方案,包括緩存回滾牲证、搜索引擎回滾哮针、消息補(bǔ)償、統(tǒng)計(jì)修正等坦袍。
10.【參考】<isEqual>中的compareValue是與屬性值對比的常量十厢,一般是數(shù)字,表示相等時帶上此條件捂齐;
<isNotEmpty>表示不為空且不為null時執(zhí)行蛮放;<isNotNull>表示不為null值時執(zhí)行

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市奠宜,隨后出現(xiàn)的幾起案子包颁,更是在濱河造成了極大的恐慌瞻想,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娩嚼,死亡現(xiàn)場離奇詭異蘑险,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)待锈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門漠其,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人竿音,你說我怎么就攤上這事和屎。” “怎么了春瞬?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵柴信,是天一觀的道長奈应。 經(jīng)常有香客問我较雕,道長,這世上最難降的妖魔是什么盏阶? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任萄涯,我火速辦了婚禮绪氛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涝影。我一直安慰自己枣察,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布燃逻。 她就那樣靜靜地躺著序目,像睡著了一般。 火紅的嫁衣襯著肌膚如雪伯襟。 梳的紋絲不亂的頭發(fā)上猿涨,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機(jī)與錄音姆怪,去河邊找鬼叛赚。 笑死,一個胖子當(dāng)著我的面吹牛稽揭,可吹牛的內(nèi)容都是我干的俺附。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼淀衣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了召调?” 一聲冷哼從身側(cè)響起膨桥,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤蛮浑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后只嚣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沮稚,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年册舞,在試婚紗的時候發(fā)現(xiàn)自己被綠了蕴掏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡调鲸,死狀恐怖盛杰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情藐石,我是刑警寧澤即供,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站于微,受9級特大地震影響逗嫡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜株依,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一驱证、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恋腕,春花似錦抹锄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至商源,卻和暖如春车份,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牡彻。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工扫沼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人庄吼。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓缎除,卻偏偏與公主長得像,于是被迫代替她去往敵國和親总寻。 傳聞我的和親對象是個殘疾皇子器罐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • ORA-00001: 違反唯一約束條件 (.) 錯誤說明:當(dāng)在唯一索引所對應(yīng)的列上鍵入重復(fù)值時,會觸發(fā)此異常渐行。 O...
    我想起個好名字閱讀 5,176評論 0 9
  • 一轰坊、MySQL優(yōu)化 MySQL優(yōu)化從哪些方面入手: (1)存儲層(數(shù)據(jù)) 構(gòu)建良好的數(shù)據(jù)結(jié)構(gòu)铸董。可以大大的提升我們S...
    寵辱不驚丶?xì)q月靜好閱讀 2,415評論 1 8
  • 阿里巴巴 JAVA 開發(fā)手冊 1 / 32 Java 開發(fā)手冊 版本號 制定團(tuán)隊(duì) 更新日期 備 注 1.0.0 阿...
    糖寶_閱讀 7,504評論 0 5
  • 比例尺用來按比例顯示數(shù)組肴沫,雖然不代表真實(shí)值粟害,但是各個數(shù)值之間關(guān)系不變。 坐標(biāo)一般與比例尺一起使用颤芬,用于標(biāo)識出不同的...
    Kenis閱讀 612評論 0 0
  • 學(xué)習(xí)溝通 記錄:今天學(xué)習(xí)練愛熊貓的《如何高效溝通》悲幅。 反思:溝通簡單的理解就是將人的興趣勾住,把事情說明白站蝠,真誠很...
    唯其時物閱讀 195評論 0 1