你應該知道的數據庫數據類型及其設計原則

1. 整數類型

整數類型有:tinyint、smallint、mediumint、int、bigint,分別使用 八、1六、2四、3二、64 位存儲空間。它們能夠存儲的值範圍從 -2 的 (n-1) 次方到 2 的 (n-1) 次方 -1,n 是存儲空間的位數。緩存

整數有可選的 unsigned 屬性(無符號類型),表示不容許有負值,所以可使正數上限提升一倍。微信

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

2. 實數類型

實數類型有:FLOAT、DOUBLE ,分別佔用 4,8 字節。優化

若是插入值的精度(即:數字總位數)高於實際定義的精度,系統會自動進行四捨五入處理,使值的精度達到要求。ui

其中 DECIMAL 也能夠用來指定精度,而且它比 FLOAT 和 DOUBLE 更適合作精確計算。在本文就不作詳細介紹了,若是有人想了解的話能夠給我留言,我下次再寫。spa

3. 字符串類型

字符串類型有:設計

  • VARCHAR
  • CHAR
  • BLOB
  • TEXT

因爲 BLOB 和 TEXT 不經常使用且因爲篇幅問題,就不展開描述了。本文主要對 VARCHAR 和 CHAR 進行介紹,它們的區別以下表:排序

對比內容 VARCHAR CHAR
是否固定長度
存儲上限字節 65535 255
保存或檢索值時,是否刪除字符串末尾空格
超過設置的範圍後,字符串是否會被截斷

除了以上不一樣以外,VARCHAR 還須要額外使用 1 個或 2 個字節來記錄字符串長度。若是列的最大長度小於或等於 255 字節,則使用 1 個字節,不然使用 2 個字節。索引

因爲 VARCHAR 是變長的,因此在 update 時,可能使行變得比原來更長,這就致使須要進行額外的工做。若是一個行佔用的空間增長,而且在頁內沒有更多空間能夠存儲,在這種狀況下,不一樣存儲引擎的處理方式不同的。例如:MyISAM 會將行拆分爲不一樣的片斷存儲,InnoDB 則須要分裂頁來使行能夠放進頁內。圖片

在選擇使用場景上,重點要抓住 VARCHAR 是變長,CHAR 是定長的特色。

好比在這些狀況更適合使用 VARCHAR:

  • 字符串的最大長度比平均長度大不少;
  • 字段更新次數少(因此碎片不是問題);
  • 使用了像 UTF-8 這樣複雜的字符集,每一個字符都使用不一樣的字節數進行存儲。

而在這些狀況則更適合使用 CHAR:

  • 存儲很短的字符串(而 VARCHAR 還要多一個字節來記錄長度,原本打算節約存儲的如今反而得不償失)
  • 定長的字符串(如 MD五、uuid);
  • 須要頻繁修改的字段。由於 VARCHAR 每次存儲都要有額外的計算,獲得長度等工做;

這裏拋出一個小問題:使用 VARCHAR(5) 和 VARCHAR(200) 來存儲 ‘hello’ 的空間開銷是同樣的。那麼使用更短的列有什麼好處呢?(思考幾秒鐘?)

答案:節約內存,由於更長的列會消耗更多的內存。MySQL 一般會分配固定大小的內存塊來保存內部值。尤爲是使用內存臨時表進行排序或操做時會特別糟糕。在利用磁盤臨時進行排序時也一樣糟糕。

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

4. 日期和時間類型

下面表格是 TIMESTAMP 和 DATETIME 的一些對比:

對比內容 TIMESTAMP DATETIME
佔用字節 4 8
時間範圍 1970-01-01 08:00:01 ~ 2038-01-19 11:14:07 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
存儲的數據是否隨時區變化

若是在插入數據時,沒有指定第一個 TIMESTAMP 列的值,MySQL 則將這個列設置爲當前時間,同時 TIMESTAMP 比 DATETIME 的空間效率更高。

最後,網上有不少討論,時間到底要使用 INT、TIMESTAMP、DATETIME 哪一種類型更適合。我認爲這沒有一個固定答案,具體能夠參考文章:《選擇合適的 MySQL 日期時間類型來存儲你的時間》,我放在原文連接裏面了。

5. 設計合理的數據類型

提供給你們 3 點設計原則:

  • 更小的一般更好
  • 簡單就好
  • 儘可能避免 NULL

下面對其詳細說明一下:

  1. 通常狀況下,應該選擇能夠正確存儲數據的最小數據類型,由於它們佔用更少的磁盤、內存和 CPU 緩存,而且處理時須要的 CPU 週期也更少。
  1. 簡單數據類型的操做須要更少的 CPU 週期。例如,整型比字符操做代價更低,由於字符集和校對規則(排序規則)使字符比較比整型比較更復雜。
  1. 一般狀況下,最好指定列爲 NOT NULL,除非真的須要存儲 NULL 值。由於可爲 NULL 的列會使索引、索引統計和值比較都更復雜。可爲 NULL 的列會使用更多的存儲空間,在 MySQL 裏也須要特殊處理。
  1. 當可爲 NULL 的列被索引時,每一個索引須要一個額外的字節,在 MyISAM 裏甚至還可能致使固定大小的索引變成可變大小的索引。一般把可爲 NULL 的列改成 NOT NULL 帶來的性能比較小,因此在優化時沒有必要先在現有表裏修改這種狀況。

參考:
《高性能 MySQL》

歡迎關注微信公衆號「不僅Java」,後臺回覆「電子書」,送說不定有你想要的呢
圖片描述

相關文章
相關標籤/搜索