從表設計說起

首先強調一點,表結構設計一定是跟業務場景息息相關的,任務脫離業務場景談表結構設計都是無稽之談。 最簡單的例子,業務場景決定了查詢語句,如果一條查詢語句要用到三張大表join聯合才能拿到需要的數據,那絕大部分情況下這都是失敗的表設計。(我就是因爲之前的人表結構設計失敗,優化花了大功夫,前端一個查詢要join5-6個表,其中有四個表還是大表...血壓拉滿)

1. 選擇合適的字段類型

首先記住三個原則。

  1. 越小越好。 (更小的數據類型意味着佔用更少的磁盤,CPU緩存,內存,並且處理時需要的CPU週期也更少。當然同時也要確保沒有低估要存儲值的範圍。)
  2. 避免使用NULL,除非有充分的理由,否則都應該設置爲NOT NULL。 如果查詢中包含可爲NULL的列,對MYSQL來說更難優化,可爲NULL的列會使用更多的存儲空間,在MYSQL中也需要特殊處理。
  3. 越簡單越好。 簡單數據類型的操作需要的CPU週期更少。例如整型比字符串的操作代價更低,使用內置時間類型比字符串好。

在爲列選擇數據類型時,第一步確定合適的大類型:數字,字符串,時間等,這通常很簡單,除了一些特殊情況。接下來細緻講一下各種大類型的下的字段設計。
有一點有必要提一下,MYSQL爲了兼容性支持很多別名,例如INTERGER,BOOL,NUMBERIC,這些只是別名。如果建表的時候採用了別名,然後用SHOW CREATE TABLE 檢查,會發現MYSQL報告的都是基本類型,而不是別名。例如建表用的BOOL,用SHOW CREATE TABLE查看類型會是tinyint類型

整數類型

整數類型有 TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT, 分別使用 8,16,24,32,64位存儲空間,存儲的值範圍從 -2 的(N-1)次方到 2的(N-1)次方,N表示位數。


整數類型有可選的 UNSIGNED字段,表示不允許負值,這會使在整數的基礎上大致加一倍。
有符號和無符號(UNSIGNED)使用相同的存儲空間,相同的性能因此可以根據實際情況選擇合適的類型。
類型選擇決定了MYSQL是怎麼在內存跟磁盤中存儲數據的
在mysql中我們還經常會爲整數類型指定寬度,例如 INT(10)之類的。這時候不要誤會,指定寬度不會影響mysql的存儲和計算,也就是說,對mysql來說 INT(1) 和 INT(10) 是一樣的。那指定寬度有什麼用呢?實際上是規定了與mysql交互的客戶端(sqlalchemy,mycli等)用來顯示字符的位數,與一些行爲。

實數類型

實數是帶有小數的數字,mysql中主要有三種類型 FLOAT, DOUBLE, DECIMAL.
FLOAT 和 DOUBLE類型支持使用標準的浮點運行進行近似計算。
DECEMAL 類型用於存儲精確的小數。
FLOAT 使用4個字節存儲,DOUBLE使用8個字節存儲。存儲相同的值時,FLOAT和DOUBLE 一般 比DECIMAL佔用的空間少。
DECIMAL雖然實現了精準存儲小數,但同時需要額外的空間和計算開銷,所以儘量只有在對小數進行精確計算時纔會用。一般的業務場景下,FLOAT與DOUBLE足夠用了。

字符串類型

字符串應該是mysql中最長使用的類型了,因此這塊內容也顯得格外重要。
mysql中最常使用的字符串類型有兩個。VARCHAR 和 CHAR, 這兩個的差別實際上跟使用的mysql引擎有關。一下關於這兩個類型的介紹全是基於innodb數據庫引擎。

VARCHAR

VARCHAR 用於存儲可變長字符串,是最常見的字符創類型。它比定廠類型更節省空間,因爲它只使用必要的存儲空間。VARCHAR需要使用 1 或者 2個額外字節記錄字符串長度,如果列的最大長度小於或者等於255個字節,則使用1個字節存儲長度,否則使用兩個字節。
VARCHAR節省了存儲空間,對性能有所幫助。但在某些情況下會影響性能。如update時數據變長了很多。這是由於該類型是變長的,所以需要額外的功能來進行存儲。

CHAR

CHAR類型是定長的。mysql總是根據定義的字符串長度分配足夠的空間。需要注意的是,mysql會刪除末尾的空格CHAR非常適合存儲定長的字符串,例如md5碼,哈希之後的密碼,uuid值等。同時對於經常變更的數據來說,CHAR比VARCHAR更好,因爲CHAR是定長,不容易產生碎片。對於非常短的列,CHAR也比VARCHAR好。


很多人在設計表的時候,都是直接用varchar(1000) 之類的來創建,雖然存儲'world'這一字符時,用到的空間是一樣的,看起來沒什麼問題。但實際上這是非常不明智的,mysql會分配固定大小的內存塊來保存內部值,尤其是使用內部臨時表進行排序或者join時,情況就會特別蛋疼,因此正確的做法應該是隻分配真正需要的空間。

BLOG 與 TEXT

這兩個數據類型是爲了存儲足夠大的字符串,其中BLOG採用二進制存儲, TEXT使用字符串存儲。

與其他類型不同,mysql把每個BLOG和TEXT的值都當做一個獨立的對象處理。存儲引擎在存儲時通常會做特殊處理,當值太大時,會使用專門的外部區域來存儲。此時每個值需要1-4個字節來存儲一個指針,然後在外部存儲實際的值。
需要注意的是。mysql 對BLOG和TEXT的進行排序與其他類型數據不一樣,他只對 前 max_sort_length 字節進行排序,而不是整個字符串。



如果覺得max_sort_length 太長,可以用substring進行截取在排序。

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