閱讀原文: 數據庫優化第一步:數據類型面試
爲何選擇合適的數據類型很重要?由於數據類型會影響存儲空間的開銷,也會影響數據的查詢效率,能夠說這是你優化數據庫的第一步要作的事情。數據庫
本文的前提環境是:MySQL 5.7 , UTF-8 Unicode微信
CHAR是固定長度,長度範圍爲0-255字符,存儲時,若是字符數沒有達到定義的位數,會在後面用空格補全存入數據庫中,比指定長度大的值將被截短。架構
VARCHAR是變長長度,長度範圍爲0-21845(utf8)或16383(utf8mb4)字符,存儲時,若是字符沒有達到定義的位數,也不會在後面補空格,固然還有一或兩個字節來描述該字節長度優化
表明的是字符,不管英文或中文 均可以存儲10個字符。ui
數字5並非表明存儲的長度,int型的長度是4字節固定的,括號裏的數字僅僅表明最小顯示的寬度。設計
那咱們設置它的意義何在呢?3d
其實當咱們長度超過5的時候它是沒用的,和沒有設置同樣,當長度沒有超過5時,而且設置了zerofill(填充零),它會在不足的從左側填充零,假如插入了數字 22 ,那麼顯示的是 00022 (navicat不顯示,可在cmd中查看)。 因此你指定的數字和它的大小及存儲的空間沒有關係。指針
int有符號數最小值:code
-2 1 4 7 4 8 3 6 4 8
總共11位
2 1 4 7 4 8 3 6 4 7
總共10位
因此你懂得…… 其它的整數類型以此類推。
由於咱們使用的是 InnoDB存儲引擎,內部的行存儲格式沒有區分固定長度和可變長度列(全部數據行都使用指向數據列值的頭指針),所以在本質上,使用固定長度的CHAR列不必定比使用可變長度VARCHAR列簡單。
Value | CHAR(4) | 實際存儲字符長度 | VARCHAR(4) | 實際存儲字符長度 |
---|---|---|---|---|
'' | ' ' | 4 bytes | '' | 1 byte |
'ab' | 'ab ' | 4 bytes | 'ab' | 3 bytes |
'abcd' | 'abcd' | 4 bytes | 'abcd' | 5 bytes |
'abcdef' | 'abcd' | 4 bytes | 'abcd' | 5 bytes |
能夠用上表來表示,當定義char時,無論你存入多少字符,都會佔用到你定義的字符數,而用varchar時,則和你輸入的字符數有關,會多一到兩個字節來記錄字節長度,當數據位佔用的字節數小於255時,用1個字節來記錄長度,數據位佔用字節數大於255時,用2個字節來記錄長度,還有一位來記錄是否爲nul值
我平時會把這篇總結當作一個字典,每次設計數據庫時忘記了會拿出來看下。
MySQL支持的數據類型主要分爲3類:
1byte = 8bit 關於位的計算可參考個人另外一篇文章《位運算》
類型 | 存儲(byte) | 符號 | 最小值(公式) | 最大值(公式) |
---|---|---|---|---|
tinyint | 1 | 有 | -128 (-27) | 127 (27-1) |
無 | 0 | 255 (28-1) | ||
smallint | 2 | 有 | -32768 (-215) | 32767 (2^15-1) |
無 | 0 | 65535 (216-1) | ||
mediuint | 3 | 有 | -8388608 (-223) | 8388607 (223-1) |
無 | 0 | 16777251 (224) | ||
int | 4 | 有 | -2147483648 (-231) | 2147483647 (231-1) |
無 | 0 | 4294967295 (232-1) | ||
bigint | 8 | 有 | -9223372036854775808 (-263) | 9223372036854775807 (263-1) |
無 | 0 | 18446744073709551615 (264-1) |
使用方式:即DECIMAL(M,D)
M的取值範圍爲1~65,取0時會被設爲默認值,超出範圍會報錯。 D的取值範圍爲0~30,並且必須<=M,超出範圍會報錯。
因此,很顯然,當M=65,D=0時,能夠取得最大和最小值。
例如: DECIMAL(5,2)
範圍: -999.99 到 999.99
若是存儲時,整數部分超出了範圍(如上面的例子中,添加數值爲1000.01),就會報錯,不容許存這樣的值。
若是存儲時,小數點部分若超出範圍,就分如下狀況:
MySQL數據類型 | 含義 |
---|---|
float(m,d) | 單精度浮點型 8位精度(4字節) m總個數,d小數位 |
double(m,d) | 雙精度浮點型 16位精度(8字節) m總個數,d小數位 |
浮點數是用來表示實數的一種方法,它用 M(尾數) * B( 基數)的E(指數)次方來表示實數,相對於定點數來講,在長度必定的狀況下,具備表示數據範圍大的特色,但同時也存在偏差問題。若是但願保證值比較準確,推薦使用定點數數據類型。
例如: float(7,4) 範圍: -999.9999 到 999.9999
MySQL保存值時進行四捨五入,所以若是在FLOAT(7,4)列內插入999.00009,近似結果是999.0001。
float和double中的M和D的取值默認都爲0,即除了最大最小值,不限制位數。
M、D範圍:
FLOAT和DOUBLE中,若M的定義分別超出7和17,則多出的有效數字部分,取值是不定的,一般數值上會發生錯誤。由於浮點數是不許確的,因此咱們要避免使用「=」來判斷兩個數是否相等。
字符串類型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。
類型名稱 | 說明 | 存儲需求 |
---|---|---|
CHAR(M) | 固定長度的非二進制字符串 | M字符,1<=M<=255 |
VARCHAR(M) | 變長的非二進制字符串 | M字符,1<=M<=21845(utf8)或16383(utf8mb4),最大上線65535字節 |
ENUM | 枚舉類型,只能有一個枚舉字符串值 | 1或2個字節,取決於枚舉值的數目(最大值是65535) |
SET | 一個設置,字符串對象能夠有零個或多個SET成員 | 1,2,3,4或8個字節,取決於集合成員的數量(最多64個成員) |
TINYTEXT | 很是小的非二進制字符串 | L+1個字節,這裏L<28 |
TEXT | 小的非二進制字符串 | L+2個字節,這裏L<216 |
MEDIUMTEXT | 中等大小的非二進制字符串 | L+3個字節,這裏L<224 |
LONGTEXT | 大的非二進制字符串 | L+4個字節,這裏L<232 |
MySQL數據類型 | 字節長度 | 含義(格式) | 範圍 |
---|---|---|---|
date | 3 | 日期 YYYY-MM-DD | '1000-01-01'到 '9999-12-31' |
time | 3 | 時間 HH:MM:SS | '-838:59:59'到'838:59:59' |
year | 1 | 年YYYY | 1901到2155 |
datetime | 8 | 日期時間 YYYY-MM-DD HH:MM:SS | '1000-01-01 00:00:00'到'9999-12-31 23:59:59' |
timestamp | 4 | 自動存儲記錄修改時間YYYY-MM-DD HH:MM:SS | '1970-01-01 00:00:01' UTC 到'2038-01-19 03:14:07' UTC |
關注微信公衆號 「碼上實戰」 回覆 :面試視頻 和 架構師 送你很是不錯的資料!