菜鳥必知的 MySQL 知識(二)—— 數(shù)據(jù)類型優(yōu)化

篇2介紹了 MySQL 幾種常用的數(shù)據(jù)類型,并介紹了同種數(shù)據(jù)類型下具體類型的區(qū)別,并在最后總結(jié)了應(yīng)當如何根據(jù)具體的業(yè)務(wù)場景選擇最合適的數(shù)據(jù)類型來建立 MySQL 數(shù)據(jù)表。

1 - MySQL 數(shù)據(jù)類型

(一) 整數(shù)
整數(shù)類型 存儲空間 字節(jié)長度
TinyInt 8 1
SmallInt 16 2
MediumInt 24 3
Int 32 4
BigInt 64 8

它們可以存儲的值的范圍從 -2^(N-1) 到 2^(N-1) - 1夕土,N為存儲空間的位數(shù)。整數(shù)類型有可選的 Unsigned 屬性时甚,表示不允許負值隘弊,這大致可以使正數(shù)的上限提高一倍哈踱。例如 TinyInt Unsigned 可以存儲的范圍是 0 ~ 255荒适,而 TINYINT 的存儲范圍是 -128 ~ 127

注意點
 int(M) M指示最大顯示寬度(最大有效顯示寬度是255)开镣,顯示寬度與存儲大小或類型包含的值的范圍無關(guān)刀诬。對于存儲和計算來說,Int(2) 和 Int(4)是相同的邪财,它們均占用4個字節(jié)陕壹,存儲范圍(-2^31 到 2^31- 1),只是在表示數(shù)字25時树埠,int(2)是25糠馆,int(4)是0025,即不足寬度會用在左邊用0補充怎憋。

(二) 浮點數(shù)
浮點數(shù)類型 字節(jié)長度 用法
Float(M,D) 4 單精度浮點數(shù)又碌,D<=24為默認Float,D>24則轉(zhuǎn)化為Double
Double(M,D) 8 雙精度浮點數(shù)
Decimal(M,D) M+1/M+2 未打包的浮點數(shù),計算中Decimal會轉(zhuǎn)換為Double
  • 單精度和雙精度的區(qū)別
     單精度 Float绊袋,一般在計算機中存儲占用4字節(jié)毕匀,也32位,有效位數(shù)為7位癌别;雙精度 Double 在計算機中存儲占用8字節(jié)皂岔,64位,有效位數(shù)為16位展姐。原因:不管float還是double 在計算機上的存儲都遵循IEEE規(guī)范躁垛,使用二進制科學計數(shù)法,都包含三個部分:符號位圾笨,指數(shù)位和尾數(shù)部分教馆。其中float的符號位,指數(shù)位墅拭,尾數(shù)部分分別為1, 8, 23活玲。 雙精度分別為1, 11, 52。 
     精度主要取決于尾數(shù)部分的位數(shù)舒憾,float為23位镀钓,除去全部為0的情況以外,最小為2的-23次方镀迂,約等于1.19乘以10的-7次方丁溅,所以float小數(shù)部分只能精確到后面6位,加上小數(shù)點前的一位探遵,即有效數(shù)字為7位窟赏。類似,double 尾數(shù)部分52位箱季,最小為2的-52次方涯穷,約為2.22乘以10的-16次方,所以精確到小數(shù)點后15位藏雏,有效位數(shù)為16位拷况。
  • Decimal的用法: 
     因為 Decimal 相比于 Float 和 Double 需要額外的空間和計算開銷,所以盡量只在對小數(shù)進行精確計算時才使用掘殴,例如存儲財務(wù)數(shù)據(jù)赚瘦。但在數(shù)據(jù)量比較大的時候,可以考慮使用 BigInt 代替 Decimal奏寨,將需要存儲的貨幣單位根據(jù)小數(shù)的位數(shù)乘以相應(yīng)的倍數(shù)即可起意。
(三) 字符串類型
  • VarChar

VarChar 用于存儲可變長字符串,比定長類型更節(jié)省空間病瞳。VarChar 需要使用1或2個額外字節(jié)記錄字符串的長度揽咕。VarChar 節(jié)省了存儲空間,對性能也有幫助仍源,但是由于行是變長的心褐,在Update時可能使行變得比原來更長,這就導致需要做額外的工作笼踩,對此不同的存儲引擎的有著自己的處理方式逗爹。

VarChar 的適合應(yīng)用于這樣的場景:字符串列的最大長度比平均長度大很多;列的更新很少嚎于,所以碎片不是問題掘而;使用了UTF-8這樣復雜的字符集,每個字符都使用不同的字節(jié)數(shù)進行存儲于购。

  • Char

Char 類型是定長的袍睡,根據(jù)定義的字符串長度分配足夠的空間。Char 適合存儲很短的字符串肋僧,或者所有值都接近同一個長度斑胜。

例如控淡,存儲密碼的MD5值,因為這是一個定長的值止潘;經(jīng)常變更的數(shù)據(jù)掺炭,Char 也比 VarChar 更好,因為定長的 Char 類型不容易產(chǎn)生碎片凭戴;對于非常短的列涧狮,Char 比 VarChar 在存儲空間上也更有效率,比如用 char(1) 來存儲只有Y和N的值么夫,如果采用單字節(jié)字符集只需要一個字節(jié)者冤,但是 varchar(1) 卻需要兩個字節(jié),因為還有一個記錄長度的額外字節(jié)档痪。

使用 varchar(5) 和 varchar(200) 存儲 'hello' 的空間開銷是一樣的涉枫,那么使用更短的列有什么優(yōu)勢嗎?
 事實證明有很大的優(yōu)勢钞它。更長的列會消耗更多的內(nèi)存拜银,因為 MySQL 通常會分配固定大小的內(nèi)存塊來保存內(nèi)部值殊鞭。尤其是使用內(nèi)存臨時表進行排序或操作時會特別糟糕遭垛。在利用磁盤臨時表進行排序時也同樣糟糕。所以最好的策略是只分配真正需要的空間操灿。

(四) 日期和時間類型
  • DataTime
     能保存大范圍的值锯仪,從 1001 年到 9999 年,精度為秒趾盐。它把日期和時間封裝到格式為 YYYYMMDDHHMMSS 的整數(shù)中庶喜,與時區(qū)無關(guān)。使用 8 個字節(jié)的存儲空間救鲤,例如 “2017-03-31 10:46:37”久窟。這是 ANSI 標準定義的日期和時間表示方法。

  • TimeStamp
     TimeStamp 只使用 4 個字節(jié)的存儲空間本缠,因此范圍比 DataTime 小斥扛,只能表示從 1970 年到 2038 年。如果在多個時區(qū)存儲或訪問數(shù)據(jù)丹锹,TimeStamp 和 DataTime 的行為將很不一樣稀颁。前者提供的值與時區(qū)有關(guān)系,后者則保留文本表示的日期和時間楣黍。
     TimeStamp 也有 DataTime 沒有的特殊屬性匾灶。默認情況下,如果插入時沒有指定第一個 TimeStamp 列的值租漂,MySQL 則設(shè)置這個列的值為當前時間阶女。TimeStamp 列默認為 NOT NULL颊糜,這也和其他數(shù)據(jù)類型不一樣。

通常應(yīng)該盡量使用 TimeStamp秃踩,因為它比 DataTime 空間效率更高芭析。

以上只是介紹了筆者在日常開發(fā)中最經(jīng)常使用的一些數(shù)據(jù)類型,相信這些類型應(yīng)該可以滿足你最基本的業(yè)務(wù)開發(fā)需求吞瞪。


2 - 數(shù)據(jù)類型優(yōu)化策略

(一) 盡量使用最小數(shù)據(jù)類型

更小的數(shù)據(jù)類型通常更快馁启,因為其占用更少的磁盤、內(nèi)存和 CPU 緩存芍秆,并且處理時需要的 CPU 周期也更少惯疙。但是要確保沒有低估需要存儲的值的范圍,因為表中多個地方增加數(shù)據(jù)類型的范圍是一個非常耗時的操作妖啥。如果無法確定哪個數(shù)據(jù)類型是最好的霉颠,就選擇你認為不會超過范圍的最小類型。

(二) 簡單就好

簡單數(shù)據(jù)類型的操作需要更少的 CPU 周期荆虱。例如蒿偎,整型比字符操作代價更低,因為字符集和校對規(guī)則使字符比較比整型比較更復雜怀读。有兩個點值得注意诉位,一是應(yīng)該使用 MySQL 內(nèi)建的類型而不是字符串來存儲日期和時間,二是應(yīng)該用整型存儲 IP 地址菜枷。

(三) 盡量避免 NULL

通常情況下最好指定列為 NOT NULL苍糠,除非真的需要存儲 NULL 值。因為如果查詢中包含可為 NULL 的列啤誊,對 MySQL 來說更難優(yōu)化岳瞭,因為可為 NULL 的列使得索引、索引統(tǒng)計和值比較都更復雜蚊锹。可為 NULL 的列會使用更多的存儲空間瞳筏,在MySQL里也需要特殊處理。當可為 NULL 的列被索引是牡昆,每個索引記錄需要一個額外的字節(jié)姚炕。


大家好,我是彬彬醬迁杨,目前在騰訊從事Web后端開發(fā)钻心。
菜鳥必知的 MySQL 知識專題整理了關(guān)于 MySQL 的基礎(chǔ)知識,適合大家進行入門級學習铅协,這個專題現(xiàn)包含下列文章:
菜鳥必知的 MySQL 知識(一)—— 基礎(chǔ)知識
菜鳥必知的 MySQL 知識(二)—— 數(shù)據(jù)類型優(yōu)化
菜鳥必知的 MySQL 知識(三)—— 索引優(yōu)化


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捷沸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子狐史,更是在濱河造成了極大的恐慌痒给,老刑警劉巖说墨,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異苍柏,居然都是意外死亡尼斧,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門试吁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棺棵,“玉大人,你說我怎么就攤上這事熄捍≈蛐簦” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵余耽,是天一觀的道長缚柏。 經(jīng)常有香客問我,道長碟贾,這世上最難降的妖魔是什么币喧? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮袱耽,結(jié)果婚禮上杀餐,老公的妹妹穿的比我還像新娘。我一直安慰自己扛邑,他們只是感情好怜浅,可當我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蔬崩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪搀暑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天,我揣著相機與錄音诈唬,去河邊找鬼久妆。 笑死,一個胖子當著我的面吹牛桂敛,可吹牛的內(nèi)容都是我干的功炮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼术唬,長吁一口氣:“原來是場噩夢啊……” “哼薪伏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起粗仓,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤嫁怀,失蹤者是張志新(化名)和其女友劉穎设捐,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體塘淑,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡萝招,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了存捺。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片槐沼。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖捌治,靈堂內(nèi)的尸體忽然破棺而出母赵,到底是詐尸還是另有隱情,我是刑警寧澤具滴,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布凹嘲,位于F島的核電站,受9級特大地震影響构韵,放射性物質(zhì)發(fā)生泄漏周蹭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一疲恢、第九天 我趴在偏房一處隱蔽的房頂上張望凶朗。 院中可真熱鬧,春花似錦显拳、人聲如沸棚愤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宛畦。三九已至,卻和暖如春揍移,著一層夾襖步出監(jiān)牢的瞬間次和,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工那伐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留踏施,地道東北人。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓罕邀,卻偏偏與公主長得像畅形,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子诉探,可洞房花燭夜當晚...
    茶點故事閱讀 44,652評論 2 354

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