mysql進階系列:表設計如何更好的選擇數據類型-第四篇

本文已參與好文召集令活動,點擊查看:後端、大前端雙賽道投稿,2萬元獎池等你挑戰!前端

公衆號:紀先生筆記mysql

平常工做中咱們會接觸到不一樣業務,一樣也會設計不一樣的表,可是你有真正考慮的mysql支持的那些數據類型嗎?知道如何根據不一樣的需求選擇最合適或者正確的類型嗎。sql

存儲字符串類型只知道選擇varchar , 是否知道字符串還有char, text, blob 。 存儲數字類型只知道選擇 int,float,double,是否知道還有tinyint,smallint 等。數據庫

看完這篇文章相信你在之後的表設計中不會再糾結究竟該使用什麼字段了。後端

優化選擇數據類型的簡單原則:

1. 更小的一般更好緩存

更小的數據類型佔用更少的磁盤,內存和CPU緩存,並且處理時須要的CPU週期也更少,因此會更快(可是要確保沒有低估須要存儲的值的範圍)markdown

2. 簡單就好函數

簡單的數據類型的操做一般須要更少的CPU週期。工具

例如:post

  1. 整型比字符串操做代價更低,由於字符集和校對規則使 字符串比較 比 整型比較 更復雜。
  2. 使用mysql自建類型而不是字符串來存儲日期和時間
  3. 用int存儲IP地址比字符串要節約空間(ip用select INET_ATON('192.1.1.101') 和 select INET_NTOA(131351321))

3. 儘可能避免null

若是查詢中包含null的列使得索引,索引統計和值比較都更爲複雜。因此若是在列上建索引,就應該儘可能避免設計成可爲null的列。

實際數據類型

1. 整數類型

可使用的整數類型存儲空間(位)由小到大分別是tinyint(8)、smallint(16)、mediumint(24)、int(32)、bigint(64)。

如何選擇:儘量使用知足需求的最小數據類型。

例如: 性別只有男和女可能還有未知,若是用數字表示就是未知(1),男(0),女(2),那麼類型能夠選擇tinyint,不必選擇其餘的更大的存儲空間的類型。

小知識點1: 整數類型中還有個可選項UNSIGNED屬性,表示不容許有負值。這可使得正整數的上限提升一倍。例如原本tinyint 能夠存儲的範圍是-128~127,而tinyint UNSIGNED 能夠存儲的範圍變成0~255(有無UNSIGNED 存儲空間都是同樣的,性能也不變)。

小知識點2: mysql中能夠設置類型的寬度,例如int(11),其實是沒有意義的,只是用來交互工具顯示字符的個數,實際上對於存儲和計算來講,int(1)和int(10) 是相同的。

2. 實數類型

實數是帶有小數部分的數字,並且不僅是爲了存儲小數部分,也可使用DECIMAL存儲比BIGINT還大的整數。

Decimal 類型用於存儲精確的小數。(CPU支持原生浮點計算,不支持對decimal的直接計算,因此浮點運算更快)。

浮點類型在存儲一樣範圍的值時,一般比decimal使用更少的空間,float用4字節存儲,double用8個字節(mysql使用double做爲內部浮點計算)

只有須要對小數進行精確計算時才使用decimal(例如財務數據),可是當數據量較大的時候,能夠考慮使用bigint代替decimal,將須要存儲的貨幣單位根據小數的位數乘以相應的倍數便可

  • 假如要存儲財務數據精確到萬分之一,能夠把全部金額乘以一百萬,

    而後將結果存儲在bigint裏,能夠避免浮點存儲計算不精確和decimal精確計算代價高的問題。

3. 字符串類型

字符串類型包含varchar(工做中首選),char,text,blob。

varchar:存儲的是可變長度字符串,比定長類型更節省空間(越短字符串使用越少的空間)。

  1. 使用最小的符合需求的長度。
  2. varchar(n) n<=255的時候使用一個字節來保存長度,當n>255的時候須要兩個字節保存長度。
  3. varchar(5)和varchar(200)保存一樣的內容,硬盤的存儲空間是同樣的,不一樣的是內存的消耗。mysql一般會分配固定大小的內存塊來保存內部值,尤爲是使用內存臨時表進行排序或者操做的時候會很糟糕。

因此最好是隻分配真正須要的空間。

應用場景:

存儲波動長度較大的數據,如:文章,有的短有的長。

字符串不多更新的場景,每次更新都會從新算並使用額外存儲空間保存長度。

適合保存多字節字符,如漢字,特殊字符等。

char: 定長,最大長度255,

存儲char值時,mysql會刪除全部數據的末尾空格,

比較適合很是短的數據,例如char(1)來存儲Y和N的值。

應用場景:

  1. 存儲長度波動不大的數據,如:md5摘要(加密後的密碼)
  2. 存儲短字符串,常常更新的字符串。

BLOB和TEXT類型

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

不建議使用,數據量很大的時候會影響效率

4. 日期和時間

dateTime8個字節的存儲空間,能夠保存大範圍的值,保存1000-01-01到9999-12-31之間的日期,精度爲秒,將日期和時間封裝到格式爲YYYYMMDDHHMMSS的整數中,與時區無關。不要使用字符串存儲日期類型,佔用空間大,損失日期類型函數的便捷性。

timestamp4個字節的存儲空間,保存了從1970年1月1日午夜(格林尼治標準時間)以來的秒數,和unix時間戳相同。timestamp的範圍只表示從1970年到2038年。timestamp的顯示的值依賴於時區。

date3個字節的存儲空間,date類型還能夠利用日期時間函數進行日期之間的計算。用於保存1000-01-01到9999-12-31之間的日期。

若是想要存儲更小粒度的日期和時間值: 可使用bigint 類型存儲微秒級別的時間戳,或者使用double存儲秒以後的小數部分

5. 枚舉類型

使用枚舉替代經常使用字符串類型,沒有生氣存儲枚舉類型會很是緊湊,會根據列表值的數據壓縮到一個或者兩個字節中,mysql會將每一個值在列表中的位置保存爲整數,而且在表的.frm文件中保存‘數字’,‘字符串’的映射關係的查找表。

若是直接在數據庫存儲枚舉性別,0表明男,1表明女,查詢的時候能夠直接看到男/女

mysql> create table enum_test( sex enum('男','女','未知') not null ) charset=utf8;

Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO enum_test(sex) values('男'),('女'),('未知'),('男');

Query OK, 4 rows affected (0.01 sec)

Records: 4 Duplicates: 0 Warnings: 0

mysql> select * from enum_test;

+--------+

| sex  |

+--------+

| 男   |

| 女   |

| 未知  |

| 男   |

+--------+

4 rows in set (0.00 sec)

-- 實際底層存儲的是整型值
mysql> select sex+0 from enum_test;
+-------+
| sex+0 |
+-------+
|     1 |
|     2 |
|     3 |
|     1 |
+-------+
4 rows in set (0.00 sec)
複製代碼

若是感受類型的選擇沒那麼重要,是由於遇到的數據體量比較小,可是若是表的數據量很大的話,就會凸顯出數據類型的重要性,合適的類型節省的空間和內存就很重要了。

一句話:最好是隻分配真正須要的空間。

相關文章
相關標籤/搜索