字段類型
? 整型
TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT 分別使用 8, 16, 24, 32, 64 位存儲(chǔ)空間,一般情況下越小的列越好。
INT(11) 中的數(shù)字只是規(guī)定了交互工具顯示字符的個(gè)數(shù)仑嗅,對(duì)于存儲(chǔ)和計(jì)算來(lái)說(shuō)是沒(méi)有意義的瘸爽。
? 浮點(diǎn)數(shù)
FLOAT 和 DOUBLE 為浮點(diǎn)類型雳灾,DECIMAL 為高精度小數(shù)類型钦睡。CPU 原生支持浮點(diǎn)運(yùn)算拯钻,但是不支持 DECIMAl 類型的計(jì)算钧嘶,因此 DECIMAL 的計(jì)算比浮點(diǎn)類型需要更高的代價(jià)棠众。
FLOAT、DOUBLE 和 DECIMAL 都可以指定列寬有决,例如 DECIMAL(18, 9) 表示總共 18 位闸拿,取 9 位存儲(chǔ)小數(shù)部分,剩下 9 位存儲(chǔ)整數(shù)部分书幕。
int(10)代表的含義:
int(10)的意思是假設(shè)有一個(gè)變量名為id新荤,它的能顯示的寬度能顯示10位。
在使用id時(shí)台汇,假如我給id輸入10苛骨,那么mysql會(huì)默認(rèn)給你存儲(chǔ)0000000010篱瞎。
當(dāng)你輸入的數(shù)據(jù)不足10位時(shí),會(huì)自動(dòng)幫你補(bǔ)全位數(shù)痒芝。
假如我設(shè)計(jì)的id字段是int(20)俐筋,那么我在給id輸入10時(shí),mysql會(huì)自動(dòng)補(bǔ)全18個(gè)0严衬,補(bǔ)到20位為止澄者。
總結(jié):
int(M)的作用于int的范圍明顯是無(wú)關(guān)的,int(M)只是用來(lái)顯示數(shù)據(jù)的寬度请琳,我們能看到的寬度粱挡。
當(dāng)字段被設(shè)計(jì)為int類型,那么它的范圍就已經(jīng)被寫(xiě)死了俄精,與M無(wú)關(guān)抱怔。
? 字符串
主要有 CHAR 和 VARCHAR 兩種類型,一種是定長(zhǎng)的嘀倒,一種是變長(zhǎng)的屈留。
字符串類型選擇策略
當(dāng)我們?yōu)樽址愋偷淖侄芜x取類型的時(shí)候,判斷該選取VARCHAR還是CHAR测蘑,我們可以從以下幾個(gè)方面來(lái)考慮:
該字段數(shù)據(jù)集的平均長(zhǎng)度與最大長(zhǎng)度是否相差很小灌危,若相差很小優(yōu)先考慮CHAR類型,反之碳胳,考慮VARCHAR類型勇蝙。
若字段存儲(chǔ)的是MD5后的哈希值,或一些定長(zhǎng)的值挨约,優(yōu)先選取CHAR類型味混。
若字段經(jīng)常需要更新,則優(yōu)先考慮CHAR類型诫惭,由于CHAR類型為定長(zhǎng)翁锡,因此不容易產(chǎn)生碎片。
對(duì)于字段值存儲(chǔ)很小的信息夕土,如性別等馆衔,優(yōu)先選取CHAR類型,因?yàn)閂ARCHAR類型會(huì)占用額外的字節(jié)保存字符串長(zhǎng)度信息怨绣。
總之一句話角溃,當(dāng)我們能夠選取CHAR類型的時(shí)候,或者說(shuō)空間消耗相對(duì)并不是影響因素的重點(diǎn)時(shí)篮撑,盡量選取CHAR類型减细,因?yàn)樵谄渌矫妫珻HAR類型都有著或多或少的優(yōu)勢(shì)赢笨。而當(dāng)空間消耗成為了很大的影響因素以后未蝌,我們則考慮使用VARCHAR類型
varchar(50)代表的含義:
varchar(50)中50的涵義最多存放50個(gè)字符驮吱,varchar(50)和(200)存儲(chǔ)hello所占空間一樣,但后者在排序時(shí)會(huì)消耗更多內(nèi)存树埠,因?yàn)閛rder by xxx采用fixed_length計(jì)算xxx長(zhǎng)度糠馆。
早期MySQL版本中50表示字節(jié)數(shù)嘶伟,現(xiàn)在表示字符數(shù)
? BLOB 和 TEXT
BLOB和TEXT都是為存儲(chǔ)很大的數(shù)據(jù)而設(shè)計(jì)的數(shù)據(jù)類型怎憋,分別采用二進(jìn)制和字符方式存儲(chǔ)。
與其他類型不同九昧,MySQL把每個(gè)BLOB和TEXT值當(dāng)做一個(gè)獨(dú)立的對(duì)象去處理绊袋。當(dāng)BLOB和TEXT值太大時(shí),InnoDB會(huì)使用專門(mén)的“外部”存儲(chǔ)區(qū)域來(lái)進(jìn)行存儲(chǔ)铸鹰,此時(shí)每個(gè)值在行內(nèi)需要1~4個(gè)字節(jié)存儲(chǔ)一個(gè)指針癌别,然后在外部存儲(chǔ)區(qū)域存儲(chǔ)實(shí)際的值。
MySQL對(duì)BLOB和TEXT列進(jìn)行排序與其他類型是不同的:它只對(duì)每個(gè)列的最前max_sort_length個(gè)字節(jié)而不是整個(gè)字符串做排序蹋笼。同樣的展姐,MySQL也不能將BLOB或TEXT列全部長(zhǎng)度的字符串進(jìn)行索引。
? 時(shí)間和日期
MySQL 提供了兩種相似的日期時(shí)間類型: DATETIME 和 TIMESTAMP剖毯。
? 1. DATETIME
能夠保存從 1001 年到 9999 年的日期和時(shí)間圾笨,精度為秒,使用 8 字節(jié)的存儲(chǔ)空間逊谋。
它與時(shí)區(qū)無(wú)關(guān)擂达。
默認(rèn)情況下,MySQL 以一種可排序的胶滋、無(wú)歧義的格式顯示 DATETIME 值板鬓,例如“2008-01-16 22:37:08”,這是 ANSI 標(biāo)準(zhǔn)定義的日期和時(shí)間表示方法究恤。
? 2. TIMESTAMP
和 UNIX 時(shí)間戳相同俭令,保存從 1970 年 1 月 1 日午夜(格林威治時(shí)間)以來(lái)的秒數(shù),使用 4 個(gè)字節(jié)部宿,只能表示從 1970 年 到 2038 年唤蔗。
它和時(shí)區(qū)有關(guān),也就是說(shuō)一個(gè)時(shí)間戳在不同的時(shí)區(qū)所代表的具體時(shí)間是不同的窟赏。
MySQL 提供了 FROM_UNIXTIME() 函數(shù)把 UNIX 時(shí)間戳轉(zhuǎn)換為日期妓柜,并提供了 UNIX_TIMESTAMP() 函數(shù)把日期轉(zhuǎn)換為 UNIX 時(shí)間戳。
默認(rèn)情況下涯穷,如果插入時(shí)沒(méi)有指定 TIMESTAMP 列的值棍掐,會(huì)將這個(gè)值設(shè)置為當(dāng)前時(shí)間。
應(yīng)該盡量使用 TIMESTAMP拷况,因?yàn)樗?DATETIME 空間效率更高作煌。
? 選擇表示符(identifier)
整數(shù)類型通常是標(biāo)識(shí)列的最佳選擇掘殴,因?yàn)樗鼈兒芸觳⑶铱梢允褂肁UTO_INCREMENT。 如果可能粟誓,應(yīng)該避免使用字符串類型作為標(biāo)識(shí)列奏寨,因?yàn)樗鼈兒芎目臻g,并且比數(shù)字類型慢鹰服。 對(duì)于完全隨機(jī)的字符串也需要多加注意病瞳,例如MD5(),SHA1()或者UUID()產(chǎn)生的字符串。這些函數(shù)生成的新值會(huì)任意分布在很大的空間內(nèi)悲酷,這會(huì)導(dǎo)致INSERT以及一些SELECT語(yǔ)句變得很慢:
因?yàn)椴迦胫禃?huì)隨機(jī)的寫(xiě)入到索引的不同位置套菜,所以使得INSERT語(yǔ)句更慢。這會(huì)導(dǎo)致葉分裂设易、磁盤(pán)隨機(jī)訪問(wèn)逗柴。
SELECT語(yǔ)句會(huì)變的更慢,因?yàn)檫壿嬌舷噜彽男袝?huì)分布在磁盤(pán)和內(nèi)存的不同地方顿肺。
隨機(jī)值導(dǎo)致緩存對(duì)所有類型的查詢語(yǔ)句效果都很差戏溺,因?yàn)闀?huì)使得緩存賴以工作的局部性原理失效。
? 選擇優(yōu)化的數(shù)據(jù)類型
更小的通常更好屠尊;更小的數(shù)據(jù)類型通常更快旷祸,因?yàn)樗鼈冋加酶俚拇疟P(pán)、內(nèi)存和CPU緩存知染,并且處理時(shí)需要的CPU周期也更少肋僧;
簡(jiǎn)單就好;例如控淡,整形比字符串操作代價(jià)更低嫌吠;實(shí)用內(nèi)建類型而不是字符串來(lái)存儲(chǔ)日期和時(shí)間;用整形存儲(chǔ)IP地址等掺炭;
盡量避免NULL辫诅;如果查詢中包含可為NULL的列,對(duì)MySQL來(lái)說(shuō)更難優(yōu)化涧狮,因?yàn)榭蔀镹ULL 的列使得索引炕矮、索引統(tǒng)計(jì)和值比較都更復(fù)雜。盡管把可為NULL的列改為NOT NULL帶來(lái)的性能提升比較小者冤,但如果計(jì)劃在列上創(chuàng)建索引肤视,就應(yīng)該盡量避免設(shè)計(jì)成可為NULL的列;