MySQL總結之數據類型

整數類型

有兩種類型的數字:整數和實數。如果存儲整數,可以使用這幾種整數類型:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT。分別使用8,16,24,32,64位存儲空間。它們可以存儲的值的範圍從-2^(N-1)到2(N-1),其中N是存儲空間的位數。

整數類型有可選的UNSIGNED屬性,表示不允許負值,這大致可以使正數的上限提高一倍。例如TINYINT UNSIGNED可以存儲的範圍是-~255,而TINYINT的存儲範圍是-128~127。

有符號和無符號類型使用相同的存儲空間,並具有相同的性能,因此可以根據實際情況選擇合適的類型。

MySQL 可以爲整數類型指定寬度,例如INT(11),對大多數應用這是沒有意義的:它不會限制值的合法範圍,只是規定了MySQL的一些交互工具(例如MySQL命令行客戶端)用來顯示字符的個數。對於存儲和計算來說,INT(1)和INT(20)是相同的。

實數類型

實數是帶有小數部分的數字。

(實際工作中還沒有使用過實數類型,因爲,小數都可以單位換算成整數,顯然在服務端使用整數比使用小數靠譜的多)。

字符串類型

VARCHAR 和 CHAR 類型

VARCHAR 和 CHAR 是兩種最主要的字符串類型。很難精確地解釋這些值是怎麼存儲在存儲磁盤和內存中的,因爲這跟存儲引擎的具體實現有關。下面的描述假設使用的存儲引擎是InnoDB 或者 MyISAM。如果使用的不是這兩種存儲引擎,請參考所使用的存儲引擎的文檔。

先看看VARCHAR和CHAR值通常在磁盤上怎麼存儲。請注意,存儲引擎存儲CHAR或者VARCHAR值的方式在內存中和在磁盤上可能不一樣,所以MySQL服務器從存儲引擎讀出的值可能需要轉換爲另一種存儲格式。

VARCHAR

VARCHAR 類型用於存儲可變長字符串,是最常見的字符串數據類型。它比定長類型更節省空間,因爲它僅使用必要的空間。有一種情況例外,如果MySQL表使用ROW_FORMAT = FIXED創建的話,每一行都會使用定長存儲,這會很浪費空間。

VARCHAR需要使用1或2個額外字節記錄字符串的長度:如果列的最大長度小於或等於255字節,則只使用1個字節表示,否則使用2個字節。

VARCHAR節省了存儲空間,所以對性能也有幫助。但是,由於行是變長的,在UPDATE時可能使行變得比原來更長,這就導致需要做額外的工作。如果一個行佔用的空間增長,並且在頁內沒有更多的空間可以存儲,在這種情況下,不同的存儲引擎的處理方式是不一樣的。例如,MyISAM會將行拆成不同的片段存儲,InnoDB則需要分裂頁來使行可以放進頁內。其他一些存儲引擎也許從不在原數據位置更新數據。

CHAR

CHAR 類型是定長的:MySQL 總是根據定義的字符串長度分配足夠的空間。當存儲CHAR值時,MySQL會刪除所有的末尾空格。CHAR值會根據需要採用空格進行填充以方便比較。

CHAR 適合存儲值很短的字符串,或者所有值都接近同一個長度。例如,CHAR非常適合存儲密碼的MD5值,因爲這是一個定長的值。對於經常變更的數據,CHAR也比VARCHAR更好,因爲定長的CHAR類型不容易產生碎片。對於非常短的列,CHAR比VARCHAR在存儲空間上也更有效率。例如用CHAR(1)來存儲只有Y和N的值,如果採用單字節字符集只需要一個字節。但是VARCHAR(1)卻需要兩個字節,因爲還有一個記錄長度的額外字節。

慷慨是不明智的

使用VARCHAR(5)和VARCHAR(200)存儲’hello’的空間開銷是一樣的。那麼使用更短的列有什麼優勢嗎?

事實證明有很大的優勢。更長的列會消耗更多的內存,因爲MySQL通常會分配固定大小的內存塊來保存內部值。尤其是使用內存臨時表進行排序或操作時會特別糟糕。在利用磁盤臨時表進行排序時也同樣糟糕。

所以最好的策略是隻分配真正需要的空間。

BLOG 和 TEXT 類型

BLOG 和TEXT 都是爲了存儲很大的數據而設計的字符串數據類型,分別採用二進制和字符方式存儲。

實際上,它們分別屬於兩組不同數據類型家族:字符類型是TINIYTEXT,SMALLTEXT,MEDIUMTEXT,LONGTEXT;對應的二進制類型是TINYBLOG,SMALLBLOG,BLOG,MEDIUMBLOG,LONGBLOG。BLOG是SMALLBLOG的同義詞。TEXT是SMALLTEXT的同義詞。

與其他類型不同,MySQL 把每個BLOG 和 TEXT 值當作一個獨立的對象處理。存儲引擎在存儲時通常會做特殊處理。當BLOG和TEXT值太大時,InnoDB會使用專門的“外部”存儲區域來進行存儲,此時每個值在行內需要1~4個字節存儲一個指針,然後在外部存儲區域存儲實際的值。

BLOG和TEXT家族之間僅有的不同是BLOG類型存儲的是二進制數據,沒有排序規則或字符集,而TEXT類型有字符集和排序規則。

日期和時間類型

MySQL 提供兩種相似的日期類型:DATETIME和TIMESTAMP。

DATETIME

這個類型能保存大範圍的值,從1001年到9999年,精度爲秒。它把是日期和時間封裝到格式爲YYYYMMDDHHMMSS的整數中,與時區無關。使用8個字節的存儲空間。

默認情況下,MySQL 以一種可排序的、無歧義的格式顯示DATETIME值,例如“2018-01-16 22:23:00”。這是ANSI標準定義的日期和時間表示方法。

TIMESTAMP

就像它的名字一樣,TIMESTAMP類型保存了從1970年1月1日午夜(格林尼治標準時間)以來的秒數,它和UNIX時間戳相同。TIMESTAMP 只使用4個字節的存儲空間,因此它的範圍比DATETIME小得多:只能表示從1970年到2038年。

MySQL 4.1以及更新的版本按照DATEYTIME的方式格式化TIMESTAMP的值,但是MySQL 4.0 以及更老的版本不會在各個部分之間顯示任何標點符號。這僅僅是顯示格式上的區別,TIMESTAMP的存儲格式在各個版本都是一樣的。

除特殊行爲外,通常也應該儘量使用TIMESTAMP,因爲它比DATETIME空間效率更高。有時候人們會將Unix時間戳存儲爲整數值,但這並不會帶來任何收益。用整數保存時間戳的格式通常不方便處理,所以不推薦這樣做。

總結

實際工作中常用的數據類型就那幾種,除了瞭解各個數據類型之間的差異,更多的是在工作中多多積累什麼情況下用什麼數據類型更合適,這是一個需要衡量的問題。

歡迎關注我的公衆號:荒古傳說

本文作者: 荒古
本文鏈接: https://haxianhe.com/2019/08/07/MySQL學習筆記之數據類型/
版權聲明: 本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 許可協議。轉載請註明出處!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章