6.財(cái)務(wù)相關(guān)的金額類數(shù)據(jù)必須使用類型
1)非精準(zhǔn)浮點(diǎn):float,
2)精準(zhǔn)浮點(diǎn):
類型為精準(zhǔn)浮點(diǎn)數(shù),在計(jì)算時(shí)不會(huì)丟失精度。占用空間由定義的寬度決定,每4個(gè)字節(jié)可以存儲(chǔ)9位數(shù)字,并且小數(shù)點(diǎn)要占用一個(gè)字節(jié)。可用于存儲(chǔ)比更大的整型數(shù)據(jù)。
7.用代替FLOAT和存儲(chǔ)精確浮點(diǎn)數(shù)
浮點(diǎn)數(shù)相對于定點(diǎn)數(shù)的優(yōu)點(diǎn)是在長度一定的情況下,浮點(diǎn)數(shù)能夠表示更大的數(shù)據(jù)范圍;浮點(diǎn)數(shù)的缺點(diǎn)是會(huì)引起精度問題
1)將字符轉(zhuǎn)化為數(shù)字
2)使用來代替ENUM類型
3)字段長度盡量按實(shí)際需要進(jìn)行分配,不要隨意分配一個(gè)很大的容量
8.使用存儲(chǔ)非負(fù)整數(shù)
同樣的字節(jié)數(shù),存儲(chǔ)的數(shù)值范圍更大。如有符號為-128-127,無符號為0-255;INT類型固定占用4個(gè)字節(jié)存儲(chǔ)
9.使用INT 存儲(chǔ)IPV4
10.使用存儲(chǔ)大小寫敏感的變長字符串
11.禁止在數(shù)據(jù)庫中存儲(chǔ)明文密碼
四、索引設(shè)計(jì)規(guī)范
建立索引的目的是:希望通過索引進(jìn)行數(shù)據(jù)查找,減少隨機(jī)IO,增加查詢性能 ,索引能過濾出越少的數(shù)據(jù),則從磁盤中讀入的數(shù)據(jù)也就越少。
索引是一把雙刃劍,可提高查詢效率,但也會(huì)降低插入和更新的速度并占用磁盤空間。
1.單張表中索引數(shù)量不超過5個(gè)
限制每張表上的索引數(shù)量,建議單張表索引不超過5個(gè)索引;索引可以提高效率同樣可以降低效率。索引可以增加查詢效率,但同樣也會(huì)降低插入和更新的效率,甚至有些情況下會(huì)降低查詢效率。優(yōu)化器在選擇如何優(yōu)化查詢時(shí),會(huì)根據(jù)統(tǒng)一信息,對每一個(gè)可以用到的索引來進(jìn)行評估,以生成出一個(gè)最好的執(zhí)行計(jì)劃,如果同時(shí)有很多個(gè)索引都可以用于查詢,會(huì)增加MySQL優(yōu)化器生成執(zhí)行計(jì)劃時(shí)間,降低查詢性能。
2.禁止給表中的每一列都建立單獨(dú)的索引
5.6版本之前,一個(gè)sql只能使用到一個(gè)表中的一個(gè)索引,5.6以后,雖然有了合并索引的優(yōu)化方式,但遠(yuǎn)沒有使用聯(lián)合索引的查詢方式效率高。
3.表必須要有主鍵
是一種索引組織表:數(shù)據(jù)的存儲(chǔ)的邏輯順序和索引的順序是相同的。
每個(gè)表都可以有多個(gè)索引,但是表的存儲(chǔ)順序只能有一種 是按照主鍵索引的順序來組織表的。不要使用更新頻繁的列作為主鍵,不適用多列主鍵(相當(dāng)于聯(lián)合索引) 不要使用UUID、MD5、HASH、字符串列作為主鍵(無法保證數(shù)據(jù)的順序增長)。
主鍵建議使用自增ID值。
4.單個(gè)索引中的字段數(shù)不超過5個(gè)
對字符串使用前綴索引,前綴索引長度不超過10個(gè)字符;
舉例:如有一個(gè)CHAR(200)列,在前10個(gè)字符內(nèi),多數(shù)值是惟一的,就可不要對整個(gè)列進(jìn)行索引。對前10個(gè)字符進(jìn)行索引能夠節(jié)省大量索引空間,也可能會(huì)使查詢更快。
5.表主鍵建議
1)表必須有主鍵,不使用更新頻繁地列作為主鍵
2)盡量不選擇字符串列作為主鍵
3)不使用UUID、MD5、HASH作為主鍵
4)默認(rèn)使用非空的唯一鍵
5)主鍵建議選擇自增或發(fā)號器重要的SQL必須被索引:
、、語句的WHERE條件列ORDER BY、GROUP BY、的字段多表JOIN的字段
6.區(qū)分度最大的字段放在索引前面
7.核心SQL優(yōu)先考慮覆蓋索引
的數(shù)據(jù)列只用從索引中就能夠取得,不必讀取數(shù)據(jù)行,換句話說查詢列要被所建的索引覆蓋。
8.避免冗余或重復(fù)索引
合理創(chuàng)建聯(lián)合索引(避免冗余),index(a,b,c)相當(dāng)于index(a)、index(a,b)、index(a,b,c)
1)索引不是越多越好,按實(shí)際需要進(jìn)行創(chuàng)建,每個(gè)額外的索引都要占用額外的磁盤空間,并降低寫操作的性能
2)不在低基數(shù)列上建立索引,例如‘性別’
3)不在索引列進(jìn)行數(shù)學(xué)運(yùn)算和函數(shù)運(yùn)算
9.盡量避免使用外鍵約束
1)不建議使用外鍵約束( key),但一定要在表與表之間的關(guān)聯(lián)鍵上建立索引;
2)外鍵可用于保證數(shù)據(jù)的參照完整性,建議在業(yè)務(wù)端實(shí)現(xiàn);
3)外鍵會(huì)影響父表和子表的寫操作從而降低性能。
10.不使用%前導(dǎo)的查詢,如like“%xxx”,無法使用索引
11.不使用反向查詢,如not in / not like
無法使用索引,導(dǎo)致全表掃描,全表掃描導(dǎo)致利用降低;
12.索引列建議
1)出現(xiàn)在、、語句的WHERE從句中的列;
2)包含在ORDER BY、GROUP BY、中的字段;
3)多表join的關(guān)聯(lián)列
注意:并不要將符合1和2中的字段的列都建立一個(gè)索引,通常將1、2中的字段建立聯(lián)合索引效果更好
13.如何選擇索引列的順序
1)區(qū)分度最高的放在聯(lián)合索引的最左側(cè)(區(qū)分度=列中不同值的數(shù)量/列的總行數(shù));
2)盡量把字段長度小的列放在聯(lián)合索引的最左側(cè)(因?yàn)樽侄伍L度越小,一頁能存儲(chǔ)的數(shù)據(jù)量越大,IO性能也就越好);
3)使用最頻繁的列放到聯(lián)合索引的左側(cè)(這樣可較少的建立一些索引)。
14.避免建立冗余索引和重復(fù)索引
冗余/重復(fù)索引會(huì)增加查詢優(yōu)化器生成執(zhí)行計(jì)劃的時(shí)間。
1)重復(fù)索引示例: key(id)、index(id)、 index(id)
2)冗余索引示例:index(a,b,c)、index(a,b)、index(a)
15.優(yōu)先考慮覆蓋索引
對于頻繁的查詢優(yōu)先考慮使用覆蓋索引。
覆蓋索引:即包含了所有查詢字段(where,, by,group by包含的字段)的索引,覆蓋索引的好處:
1)避免表進(jìn)行索引的二次查詢
是以聚集索引的順序來存儲(chǔ)的,對于來說,二級索引在葉子節(jié)點(diǎn)中所保存的是行的主鍵信息,如果是用二級索引查詢數(shù)據(jù),在查找到相應(yīng)的鍵值后,還需通過主鍵進(jìn)行二次查詢才能獲取我們真實(shí)所需要的數(shù)據(jù)。
而在覆蓋索引中,二級索引的鍵值中可以獲取所有的數(shù)據(jù),避免了對主鍵的二次查詢 ,減少了IO操作,提升了查詢效率。
2)可以把隨機(jī)IO變成順序IO加快查詢效率
由于覆蓋索引是按鍵值的順序存儲(chǔ)的,對于IO密集型的范圍查找來說,對比隨機(jī)從磁盤讀取每一行的數(shù)據(jù)IO要少的多,因此利用覆蓋索引在訪問時(shí)也可以把磁盤的隨機(jī)讀取的IO轉(zhuǎn)變成索引查找的順序IO。
五、SQL開發(fā)規(guī)范
1.建議使用預(yù)編譯語句進(jìn)行數(shù)據(jù)庫操作
預(yù)編譯語句可以重復(fù)使用這些計(jì)劃,減少SQL編譯所需要的時(shí)間,還可以解決動(dòng)態(tài)SQL所帶來的SQL注入的問題 只傳參數(shù),比傳遞SQL語句更高效 相同語句可以一次解析,多次使用,提高處理效率。
2.避免數(shù)據(jù)類型的隱式轉(zhuǎn)換
隱式轉(zhuǎn)換會(huì)導(dǎo)致索引失效。
3.充分利用表上已經(jīng)存在的索引
1)避免使用雙%號的查詢條件。
如無前置%,只有后置%,是可以用到列上的索引的
2)一個(gè)SQL只能利用到復(fù)合索引中的一列進(jìn)行范圍查詢
解說:有 a,b,c列的聯(lián)合索引,在查詢條件中有a列的范圍查詢,則在b,c列上的索引將不會(huì)被用到,在定義聯(lián)合索引時(shí),如果a列要用到范圍查找的話,就要把a(bǔ)列放到聯(lián)合索引的右側(cè)。使用left join或 not 來優(yōu)化not in操作,因not in 也通常會(huì)使用索引失效。
4.數(shù)據(jù)庫設(shè)計(jì)時(shí),應(yīng)該要對以后擴(kuò)展進(jìn)行考慮
5.程序連接不同的數(shù)據(jù)庫使用不同的賬號,進(jìn)制跨庫查詢
1)為數(shù)據(jù)庫遷移和分庫分表留出余地
2)降低業(yè)務(wù)耦合度
3)避免權(quán)限過大而產(chǎn)生的安全風(fēng)險(xiǎn)
6.強(qiáng)烈不建議使用 * ;推薦使用 查詢
原因:
1)消耗更多的CPU和IO以網(wǎng)絡(luò)帶寬資源
2)無法使用覆蓋索引
3)可減少表結(jié)構(gòu)變更帶來的影響
7.禁止使用不含字段列表的語句
舉例: into ('a','b','c');
應(yīng)使用 into t(c1,c2,c3) ('a','b','c');
8.避免使用子查詢,可把子查詢優(yōu)化為join操作
通常子查詢在in子句中,且子查詢中為簡單SQL(不包含union、group by、order by、limit從句)時(shí),才可以把子查詢轉(zhuǎn)化為關(guān)聯(lián)查詢進(jìn)行優(yōu)化。
子查詢性能差的原因:
1)子查詢的結(jié)果集無法使用索引,通常子查詢的結(jié)果集會(huì)被存儲(chǔ)到臨時(shí)表中,不論是內(nèi)存臨時(shí)表還是磁盤臨時(shí)表都不會(huì)存在索引,所以查詢性能 會(huì)受到一定的影響;
2)特別是對于返回結(jié)果集比較大的子查詢,其對查詢性能的影響也就越大;
3)由于子查詢會(huì)產(chǎn)生大量的臨時(shí)表也沒有索引,所以會(huì)消耗過多的CPU和IO資源,產(chǎn)生大量的慢查詢。
9.避免使用JOIN關(guān)聯(lián)太多表
MySQL最擅長的是單表的主鍵/二級索引查詢,MySQL存在關(guān)聯(lián)緩存的,緩存的大小可以由參數(shù)進(jìn)行設(shè)置。在MySQL中,對于同一個(gè)SQL多關(guān)聯(lián)(join)一個(gè)表,會(huì)多分配一個(gè)關(guān)聯(lián)緩存,如果在一個(gè)SQL中關(guān)聯(lián)的表越多,所占用的內(nèi)存也就越大。
Join消耗較多的內(nèi)存,產(chǎn)生臨時(shí)表;
如程序中大量的使用了多表關(guān)聯(lián)的操作,同時(shí)設(shè)置的也不合理的情況下,就容易造成服務(wù)器內(nèi)存溢出的情況,就會(huì)影響到服務(wù)器數(shù)據(jù)庫性能的穩(wěn)定性。
同時(shí)對于關(guān)聯(lián)操作來說,會(huì)產(chǎn)生臨時(shí)表操作,影響查詢效率MySQL最多允許關(guān)聯(lián)61個(gè)表,但業(yè)務(wù)生產(chǎn)環(huán)境中建議不超過5個(gè)。
10.減少同數(shù)據(jù)庫的交互次數(shù)
1)數(shù)據(jù)庫更適合處理批量操作 合并多個(gè)相同的操作到一起,可以提高處理效率。
11.對應(yīng)同一列進(jìn)行or判斷時(shí),使用in代替or
不要超過500個(gè)in操作可以更有效的利用索引,or大多數(shù)情況下很少能利用到索引。
12.禁止使用order by,rand() 進(jìn)行隨機(jī)排序
隨機(jī)排序會(huì)把表中所有符合條件的數(shù)據(jù)裝載到內(nèi)存中,然后在內(nèi)存中對所有數(shù)據(jù)根據(jù)隨機(jī)生成的值進(jìn)行排序,并且可能會(huì)對每一行都生成一個(gè)隨機(jī)值,如果滿足條件的數(shù)據(jù)集非常大,就會(huì)消耗大量的CPU和IO及內(nèi)存資源。
簡單來說:order by數(shù)據(jù)庫基本語句大全,rand()會(huì)將數(shù)據(jù)從磁盤中讀取,進(jìn)行排序,會(huì)消耗大量的IO和CPU。
推薦在程序中獲取一個(gè)隨機(jī)值,然后從數(shù)據(jù)庫中獲取對應(yīng)的數(shù)據(jù)。
13.WHERE從句中禁止對列進(jìn)行函數(shù)轉(zhuǎn)換和計(jì)算
對列進(jìn)行函數(shù)轉(zhuǎn)換或計(jì)算時(shí)會(huì)導(dǎo)致無法使用索引。
14.在明顯不會(huì)有重復(fù)值時(shí)使用UNION ALL而不是UNION
1)UNION會(huì)把兩個(gè)結(jié)果集的所有數(shù)據(jù)放到臨時(shí)表中后再進(jìn)行去重操作;
2)UNION ALL不會(huì)再對結(jié)果集進(jìn)行去重操作。
15.拆分復(fù)雜的大SQL為多個(gè)小SQL
原因如下:
1)大SQL:邏輯上比較復(fù)雜,需要占用大量CPU進(jìn)行計(jì)算;
2)MySQL:一個(gè)SQL只能使用一個(gè)CPU進(jìn)行計(jì)算;
3)SQL拆分后可以通過并行執(zhí)行來提高處理效率。
16.避免使用存儲(chǔ)過程、觸發(fā)器、等
1)降低業(yè)務(wù)耦合度,為分庫分表、留點(diǎn)余地;
2)改策略可有效規(guī)避BUG。
17.避免在數(shù)據(jù)庫中進(jìn)行數(shù)學(xué)運(yùn)算
1)容易將業(yè)務(wù)邏輯和DB耦合在一起
2)MySQL不擅長數(shù)學(xué)運(yùn)算和邏輯判斷
3)無法使用索引
六、操作行為規(guī)范
1.超100萬行的批量寫(、、)操作,要分批多次進(jìn)行操作
1)大批量操作可能會(huì)造成嚴(yán)重的主從延遲。
主從環(huán)境中,大批量操作可能會(huì)造成嚴(yán)重的主從延遲,大批量的寫操作一般都需要執(zhí)行一定長的時(shí)間,只有當(dāng)主庫上執(zhí)行完成后數(shù)據(jù)庫基本語句大全,才會(huì)在其他從庫上執(zhí)行,會(huì)造成主庫與從庫長時(shí)間的延遲情況。
2)日志為row格式時(shí)會(huì)產(chǎn)生大量的日志
大批量寫操作會(huì)產(chǎn)生大量日志,特別是對于row格式二進(jìn)制數(shù)據(jù)而言,由于在row格式中會(huì)記錄每一行數(shù)據(jù)的修改,一次修改的數(shù)據(jù)越多,產(chǎn)生的日志量也會(huì)越多,日志的傳輸和恢復(fù)所需要的時(shí)間也就越長,這也是造成主從延遲的一個(gè)原因。
3)避免產(chǎn)生大事務(wù)操作
大批量修改數(shù)據(jù),一定是在一個(gè)事務(wù)中進(jìn)行的,這會(huì)造成表中大批量數(shù)據(jù)進(jìn)行鎖定,導(dǎo)致大量的阻塞,阻塞會(huì)對MySQL的性能影響很大。尤其是長時(shí)間的阻塞會(huì)占滿所有數(shù)據(jù)庫的可用連接,會(huì)使生產(chǎn)環(huán)境中的其他應(yīng)用無法連接到數(shù)據(jù)庫,因此一定要注意大批量寫操作要進(jìn)行分批。
2.對于大表使用pt---修改表結(jié)構(gòu)
1)可避免大表修改產(chǎn)生的主從延遲
2)可避免在對表字段進(jìn)行修改時(shí)進(jìn)行鎖表
生產(chǎn)環(huán)境中,對大表數(shù)據(jù)結(jié)構(gòu)的修改一定要謹(jǐn)慎,會(huì)造成嚴(yán)重的鎖表操作;
pt---首先建立一個(gè)與原表結(jié)構(gòu)相同的新表,并且在新表上進(jìn)行表結(jié)構(gòu)的修改,然后再把原表中的數(shù)據(jù)復(fù)制到新表中,并在原表中增加一些觸發(fā)器。
把原表中新增的數(shù)據(jù)也復(fù)制到新表中,在行所有數(shù)據(jù)復(fù)制完成之后,把新表命名成原表,并把原來的表刪除掉。把原來一個(gè)DDL操作,分解成多個(gè)小批次作業(yè)進(jìn)行。
這也是對表進(jìn)行碎片整理/重組的一個(gè)常用方式。
3.禁止為程序使用的賬號賦予super權(quán)限
原因:當(dāng)MySQL 達(dá)到最大連接數(shù)限制時(shí),此刻還運(yùn)行1個(gè)有super權(quán)限的用戶連接,super權(quán)限只能留給DBA處理問題的賬號使用。
4.對于程序連接數(shù)據(jù)庫賬號,遵循權(quán)限最小原則程序
使用數(shù)據(jù)庫賬號只能在一個(gè)DB下使用,不準(zhǔn)跨庫 程序使用的賬號原則上不準(zhǔn)有drop權(quán)限。
其他一些操作規(guī)范:
5.任何數(shù)據(jù)庫的線上操作,必須走工單
6.禁止在主庫上執(zhí)行統(tǒng)計(jì)類的功能查詢;
7.有大規(guī)模市場推廣、運(yùn)營活動(dòng)必須提前通知DBA進(jìn)行流量評估;
8.對單表的多次alter操作必須合并為一次操作;
9.不在MySQL數(shù)據(jù)庫中存放業(yè)務(wù)邏輯,即可創(chuàng)建存儲(chǔ)過程;
10.重大項(xiàng)目的數(shù)據(jù)庫方案選型和設(shè)計(jì)必須提前通知DBA參與;
11.數(shù)據(jù)必須有備份機(jī)制和定期的恢復(fù)演練;
12.不在業(yè)務(wù)高峰期批量更新、查詢數(shù)據(jù)庫;
文章至此。