現代數據庫通常都支持CHAR與VARCHAR字符型字段類型,CHAR是用來保存定長字符,存儲空間的大小爲字段定義的長度,與實際字符長度無關,當輸入的字符小於定義長度時最後會補上空格。VARCHAR是用來保留變長字符,在數據庫中存儲空間的大小是實際的字符長度,不會像CHAR同樣補上空格,這樣佔用的空間更少。
從以上特色來看,VARCHAR比CHAR有明顯的優點,所以大部份數據庫設計時都應該採用VARCHAR類型。那爲何還須要CHAR類型呢,我的認爲有如下幾個緣由:
一、爲了跟之前版本的數據庫進行一個兼容,由於好久之前數據庫只支持CHAR類型,有些應用的業務邏輯也只是針對CHAR類型設計的,因此數據庫軟件也就一直保留CHAR類型。
二、CHAR類型是定長的,一些數據庫能夠在每條記錄中不存儲字段長度信息,這樣能夠節省部份空間,也能夠方便作一些內存對齊提升性能,但我的認爲這帶來的性能提高很是微小,至少ORACLE數據庫是沒有意義的。
三、還有說法是有些數據常常修改,長度可能變化,會引發碎片,採用CHAR就不會產生碎片,這個說法比較多,但我認爲既然長度會變化,那用VARCHAR更能節省內存與存儲空間來提高性能,只要數據塊預留的空間沒有問題,採用VARCHAR性能更好。
對於ORACLE數據庫,我找不到充足的理由來使用CHAR類型,並且CHAR還會帶來討厭的空格,有些文章說MYSQL的MYISAM存儲引擎在和長度固定的狀況下CHAR比VARCHAR好,這個沒有測試過,不太瞭解。
因爲VARCHAR是變長存儲,那麼不少人會有疑問,好比STATUS字段定義VARCHAR(10)與VARCHAR(1000)有什麼區別,反正是變長的,存儲空間都同樣,免得之後要加長又要改變字段定義。 下面說一下個人理解:
一、字段長度是數據庫一種約束,能夠保證進入數據庫的數據符合長度要求,定義合理的字段長度能夠減小一部份非法數據進入,好比:咱們業務中STATUS只有‘NEW’,‘DELETE’,‘CLOSE’3種狀態,使用VARCHAR(5)保存,這樣能夠有效的減小非法數據進入,定義合理的長度也可讓人容易理解字段的用途,試想一下,若是你全部的字符字段長度都是VARCHAR(4000)會是什麼樣的狀況。 sql
二、VARCHAR的字段長度雖然對數據存儲沒有太大影響,但對特定的數據庫仍是有一些細微差異,好比MYSQL中定義的長度若是小於255,字段長度用1個字節表示,若是超過255,字段的長度將固定用2個字節表示。若是你的業務數據最大長度只有10,但定義長度爲256則每條記錄會多浪費了一個字節來存儲長度。ORACLE沒有這樣的問題,它會根據每條記錄字段的實際長度動態選擇長度標識。 數據庫
三、字段定義的長度對索引也有較大影響。ORACLE對索引長度仍是有必定限制,8i官方文檔說明單條記錄索引信息的長度不能超過數據塊大小的40%,9i中是75%,實際上也差很少,具體能夠見jametong的http://www.dbthink.com/?p=20這篇文檔,裏面有詳細的測試結果。若是你的數據塊大小是8K,那麼索引字段的定義長度不能超過6398,好比,你要給表上2個VARCHAR(4000)字段建組合索引,建立時會直接報錯。另外索引組織表及在線重建索引(由於中間會臨時建立一個索引組織表)容許的索引信息長度更小,只能是數據塊大小的40%,實際中8K的數據塊大小,要使用在線重建索引,那定義的長度不能超過3215。從以上能夠看出,數據塊大小爲8K時,設計字段時若是要定義爲VARCHAR(4000),那這個字段就不能考慮創建索引,由於即便能建上,也不能作在線重定義操做,DBA要進行索引維護時只能中止應用,這將對系統的可用性產生較大影響。關於ORACLE索引長度限制測試的腳本以下: 服務器
五、關於字段長度對齊的問題,有些設計人員喜歡定義字段的長度爲4或者8的倍數,如16,32,64,128之類的,理由是能夠作到內存對齊,對於這個問題我沒有深刻分析過,我的認爲必要性不大,也沒看到過這種優化能提高性能的案例。若是一個VARCHAR(1)定義爲VARCHAR(4)反而浪費內存與存儲,實際上我看到在ORACLE jdbc驅動中會將全部的字符類型數據保存在一個大的char[]中,把全部NUMBER與DATE類型放在另外一個char[]中,這樣整合後都不清楚如何內存對齊了。
綜上所述:VARCHAR類型字段長度不能隨便定義,並非越大越好,仍是須要根據實際業務數據定義一個合適的長度。我我的對於一些能夠徹底預估的長度就按實際長度定義,好比年月、狀態、標記之類的信息。對於不肯定長度的業務數據如NAME、STYLE之類的信息定義一個合理值,如VARCHAR(20),VARCHAR(30) 之類 。對於描述性或備註性的信息,這些字段也肯定不會有索引,長度也不可預知,因此留更大的長度,避免之後常常進行長度調整,如VARCHAR(1024),或者直接VARCHAR2(4000) 。 併發