數據庫Schema設計中數據類型對性能影響需要考慮的要點

實際上在很多數據庫的設計優化文檔中都有關於通過優化數據類型的優化說明內容,在我們同樣也可以通過數據類型的優化達到優化整個Schema 設計的目的。

 

優化數據類型提高性能的主要原理在於以下幾個方面:

        1. 通過選用更“小”的數據類型減少存儲空間,使查詢相同數據需要的I/O資源降低;

        2. 通過合適的數據類型加速數據的比較;

 

下面我們還是通過分析一些常用數據類型的數據存儲格式和長度來看看哪些數據類型可以在優化中 利用上。

 

數字類型:

對於數字類型,這裏分別列出了整數類型和小數類型,也就是浮點數類型。實際上,還有一類通過二進制格式以字符串來存放的數字類型,如DECIMAL(DEC)[(M[,D])],NUMERIC[(M[,D])],由於其存放長度主要通過其定義時候的的 M 所決定,M 定義爲多大,則實際存放就有多長。M 代表整個位數長度,而 D 則 表示小數點後的位數,默認M 爲10,D爲0。一般來說,主要用在固定精度的場合,由於其存放長度較大,而且考慮到這種數據完全可以變化形式以整數存放,所以筆者個人並不是特別推薦。

對於數字的存儲,一般使用到浮點型數據的場合也不應該太多。主要出於兩個原因:一個是浮點型數據本身實際上是一個並不精確的數字,只是一個近似值,另一個原因就是完全可以通過乘以一個固定 的係數轉換爲整型數據來存放。這樣不僅可以解決數據不精確的問題,同時也讓數據的處理更爲高效。

 

時間類型:

時間存儲格式總類並不是太多,我們常用的主要就是 DATETIME,DATE 和 TIMESTAMP 這三種了。從存儲空間來看 TIMESTAMP 最少,四個字節,而其他兩種數據類型都是八個字節,多了一倍。而TIMESTAMP 的 缺點在於他只能存儲從1970 年之後的時間,而另外兩種時間類型可以存放最早從1001 年開始的時間。如 果有需要存放早於1970 年之前的時間的需求,我們必須放棄 TIMESTAMP類型,但是隻要我們不需要使用1970 年之前的時間,最好儘量使用 TIMESTAMP 來減少存儲空間的佔用。

上面所列出的主要是一些存放固定長度,且我們平時可能常用到的一些類型。通過這個對照表格, 我們可以很直觀的看出哪種類型佔用的存儲空間大,哪種佔用的空間小。這樣,在數據類型選擇的時 候,我們就可以結合各種類型的存儲範圍以及業務中可能存在的數據作出對應,然後選擇存儲空間最先 的類型來使用。

 

字符存儲類型

CHAR[(M)]類型屬於靜態長度類型,存放長度完全以字符數來計算,所以最終的存儲長度是基於字符 集的,如 latin1 則最大存儲長度爲 255 字節,但是如果使用 gbk 則最大存儲長度爲 510 字節。CHAR 類型 的存儲特點是不管我們實際存放多長數據,在數據庫中都會存放M 個字符,不夠的通過空格補上,M 默認 爲1。雖然CHAR會通過空格補齊存放的空間,但是在訪問數據的時候,MySQL會忽略最後的所有空格,所以如果我們的實際數據中如果在最後確實需要空格,則不能使用CHAR 類型來存放。在 MySQL5.0.3 之前的 版本中,如果我們定義 CHAR 的時候 M 值超過 255,MySQL會自動將 CHAR 類型進行轉換爲可以存入對應數 據量的 TEXT 類型,如CHAR(1000)會自動轉換爲 TEXT,CHAR(10000)則會轉爲 MEDIUMTEXT。而從 MySQL5.0.3 開始,所有超過 255 的定義 MySQL 都會直接拒絕並給出錯誤信息,不再自動轉換。

VARCHAR[(M)]屬於動態存儲長度類型,僅存佔用實際存儲數據的長度。其存放的最大長度與 MySQL 版本有關,在 5.0.3 之前的版本 VARCHAR 以字符數控制最存儲的最大長度,最大隻能存放255 個字符,佔 用存儲空間的實際大小與字符集有關。但是從5.0.3 開始,VARCHAR 的最大存儲限制已經更改爲字節數限 制了,擴展到可以存放 65535 bytes 的數據,不同的字符集可能存放的字符數並不一樣。也就是說,在 MySQL5.0.3之前的版本,M所代表的是字符數,而從 5.0.3版本開始,M的代表意思已經是字節數了。 VARCHAR 的存儲特點是不管我們設定 M 爲多大的值,真正佔用的存儲空間都只有我們所存入的實際數據的 大小,和 CHAR 不同的是 VARCHAR 會保留我們存入數據最後的空格,也就是說我們存入是什麼樣, MySQL 返回給我們的也會是什麼樣。在VARCHAR 類型字段的數據中,MySQL 會在每個 VARCHAR 數據中使用 1 個或 者 2 個字節用來存放 VARCHAR 數據的實際長度,當我們的實際數據在255 字節之內的時候,會使用 1 字節 來存放實際長度,而大於 255 字節的時候,則需要使用 2 字節來存放。

TINYTEXT,TEXT,MEDIUMTEXT 和 LONGTEXT 這四種類型同屬於一種存儲方式,都是動態存儲長度類類型,不同的僅僅是最大長度的限制。四種類型的定義都是通過最大字符數來限制,但是他們的字符數限 制實際上是可以理解爲字節數限制的,因爲當我們使用多字節字符集的時候,實際能存放的字符書並沒 最大字符數那麼多,而是以單字節字符來計算的字符數。此外,由於是動態存儲長度類型,所以和VARCHAR 一樣,每個字段數據之前都需要一個存放實際長度的空間。TINYTEXT 需要 1 個字節來存放,TEXT 需要 2 個字節,MEDIUMTEXT 和 LONGTEXT 則分別需要 3 個和 4 個字節來存放實際數據長度。實際上,出了 MySQL 內嵌的最大長度限 制之外,他們還受到客戶端與服務器端的網絡通信緩衝區最大值 (max_allowed_packet)的限制。

這四種 TEXT 類型和 CHAR 及 VARCHAR 在實際使用中存在幾個不一樣的地方:

◆ 不能設置默認值;
◆ 只有 TEXT 可以使用 TEXT[(M)]這樣的方式通過 M 設置大小;
◆ 基於這四種類型的索引必須指定前綴長度;

 

其他常用類型:

除了上面這些字段類型之外會被我們經常使用到之外,我們還會使用到的數據類型主要有以下這些。

對於BIT類型,M表示每個值的bits數目,默認爲1,最大爲64 bits。對於MySQL來說這是一個新的類型,因爲從MySQL5.0.3纔開始真正實現(在之前實際上是 TINYINT(1)),而且僅僅支持 MyISAM 存儲引擎,但是從 MySQL5.0.5 開始 Memory,Innodb 和 NDB Cluster 存儲引擎也開始 “支持”了。在 MyISAM 中,BIT的存儲空間很小,是真正的實現了通過bit 來存儲,但是在其他的一些存儲引擎中就不一樣了,因爲他們是轉換爲最小的INT 類型存儲的,所以佔用的空間也沒有節省,還不如直接使用 INT 類的 數據類型存放來得直觀。

對於 SET 和 ENUM 類型,主要內容基本處於較少變化狀態且值比較少的字段。雖然這兩個字段所佔用的存儲空間都較少,但是由於在使用方面較其他的數據類型要略爲複雜一些,所以在實際環境中一般使 用還是較少。

衆所周知,數據量(這裏主要指數據記錄條數)的增加肯定會讓數據庫的檢索查詢效率降低。所以很多時候人們大都希望通過減少數據庫中關鍵表的記錄條數來獲得數據庫性能的提升。實際上,除了這 種通過控制數據記錄條數來控制數據總量的辦法之外,我們還可以通過選擇更小的數據類型來讓數據庫通過更小的空間存放相同的數據量,這對於檢索同樣的數據所帶來的I/O消耗自然會降低,性能也就很自然得到了提升。

此外,由於 CPU對不同數據的處理方式不一樣,就會造成不同類型的數據在各種運算處理如比較排序等方面的處理效率存在差異。所以,對於我們需要經常進行比較計算以及排序等消耗 CPU資源的字段,應該儘量選擇處理更爲迅速的字段類型。如通過整數類型代替浮點數或者字符類型。

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