數據庫優化第一步:數據類型

閱讀原文:數據庫優化第一步:數據類型html

爲何選擇合適的數據類型很重要?由於數據類型會影響存儲空間的開銷,也會影響數據的查詢效率,能夠說這是你優化數據庫的第一步要作的事情。mysql

疑問

本文的前提環境是:MySQL 5.7 , UTF-8 Unicodesql

char與varchar的區別和選擇?

  • CHAR是固定長度,長度範圍爲0-255字符,存儲時,若是字符數沒有達到定義的位數,會在後面用空格補全存入數據庫中,比指定長度大的值將被截短。
  • VARCHAR是變長長度,長度範圍爲0-21845(utf8)或16383(utf8mb4)字符,存儲時,若是字符沒有達到定義的位數,也不會在後面補空格,固然還有一或兩個字節來描述該字節長度

varchar(10) 括號中的數字表明 字節 仍是 字符 ?

表明的是字符,不管英文或中文 均可以存儲10個字符。數據庫

int(5) 括號中的數字表明 什麼 ?

數字5並非表明存儲的長度,int型的長度是4字節固定的,括號裏的數字僅僅表明最小顯示的寬度。優化

  • 那咱們設置它的意義何在呢?

    其實當咱們長度超過5的時候它是沒用的,和沒有設置同樣,當長度沒有超過5時,而且設置了zerofill(填充零),它會在不足的從左側填充零,假如插入了數字 22 ,那麼顯示的是 00022 (navicat不顯示,可在cmd中查看)。ui

因此你指定的數字和它的大小及存儲的空間沒有關係。spa

int 括號中的數字爲何默認11或10 ?

int有符號數最小值:.net

-2 1 4 7 4 8 3 6 4 8 總共11位設計

2 1 4 7 4 8 3 6 4 7 總共10位指針

因此你懂得…… 其它的整數類型以此類推。

如今爲何不多使用CHAR ?

由於咱們使用的是 InnoDB存儲引擎,內部的行存儲格式沒有區分固定長度和可變長度列(全部數據行都使用指向數據列值的頭指針),所以在本質上,使用固定長度的CHAR列不必定比使用可變長度VARCHAR列簡單。

Value   CHAR(4)  實際存儲 VARCHAR(4)  實際存儲
'' ' ' 4 bytes '' 1 bytes
'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)
<br/> <br/> 0 255 (28-1)
smallint 2 -32768 (-215) 32767 (215-1)
<br/> <br/> 0 65535 (216-1)
mediuint 3 -8388608 (-223) 8388607 (223-1)
<br/> <br/> 0 16777251 (224)
int 4 -2147483648 (-231) 2147483647 (231-1)
<br/> <br/> 0 4294967295 (232-1)
bigint 8 -9223372036854775808 (-263) 9223372036854775807 (263-1)
<br/> <br/> 0 18446744073709551615 (264-1)

定點型

使用方式:即DECIMAL(M,D)

  • M 表示十進制數字總的個數
  • D 表示小數點後面數字的位數
  • M的默認取值爲10,D默認取值爲0。若是建立表時,某字段定義爲decimal類型不帶任何參數,等同於decimal(10,0)。帶一個參數時,D取默認值。

M的取值範圍爲1~65,取0時會被設爲默認值,超出範圍會報錯。
D的取值範圍爲0~30,並且必須<=M,超出範圍會報錯。

因此,很顯然,當M=65,D=0時,能夠取得最大和最小值。

舉例

例如: DECIMAL(5,2)
範圍: -999.99 到 999.99

若是存儲時,整數部分超出了範圍(如上面的例子中,添加數值爲1000.01),就會報錯,不容許存這樣的值。

若是存儲時,小數點部分若超出範圍,就分如下狀況:

  1. 若四捨五入後,整數部分沒有超出範圍,則只警告,但能成功操做並四捨五入刪除多餘的小數位後保存。如999.994實際被保存爲999.99。
  2. 若四捨五入後,整數部分超出範圍,則報錯,並拒絕處理。如999.995和-999.995都會報錯。

浮點型

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,即除了最大最小值,不限制位數。容許的值理論上是-1.7976931348623157E+308~-2.2250738585072014E-30八、0和2.2250738585072014E-308~1.7976931348623157E+308。

M、D範圍:

  • M取值範圍爲0~255。FLOAT只保證6位有效數字的準確性,因此FLOAT(M,D)中,M<=6時,數字一般是準確的。若是M和D都有明肯定義,其超出範圍後的處理同decimal。
  • D取值範圍爲0~30,同時必須<=M。double只保證16位有效數字的準確性,因此DOUBLE(M,D)中,M<=16時,數字一般是準確的。若是M和D都有明肯定義,其超出範圍後的處理同decimal。

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

日期類型的選擇

  • 若是你的應用不牽涉到時區/國際業務,那麼你最好選擇datetime/timestamp,可讀性高,統計方便。
  • 若是你的應用牽涉的時區或國際業務,大家建議你使用bigint/timestamp來存儲時間戳,這樣沒有時區的困擾,但bigint可讀性差。
  • 若是你認爲你的應用可以運行到2037年之後,那麼別用timestamp。

選擇合適的類型

這裏指的是數據列的數據類型,在選擇合適的數據類型時,咱們應知足如下條件:

  • 儘可能選擇小,簡單的數據類型。
  • 保持可讀性。
  • 儘可能避免Null

clipboard.png

歡迎關注公衆號交流!
更多關注

參考

https://dev.mysql.com/doc/ref...

https://dev.mysql.com/doc/ref...

https://www.edureka.co/blog/m...

https://stackoverflow.com/que...

https://blog.csdn.net/vkingne...

相關文章
相關標籤/搜索