MySQLのchar和varchar

MySQLのchar和varchar

char和varchar是2種字符串類型,char(N)保存固定長度的字符串,
N範圍:0~255(2^8-1);varchar(N)保存變長字符串,N範圍:0~65535(2^16-1)。其中
N表示字符長度

對char類型字符串,MySQL數據庫會自動對存儲列的右邊進行填充
操作,直接字符串達到指定的長度N。而在讀取列時,MySQL會自動
將填充的字符刪除。而在進行數據比較時,系統又會將空格填充到
字符串的末尾,如果顯示將SQL_MODE設置爲:PAD_CHAR_TO_FULL_LENGTH
除外.
注意些函數:
length函數:字節長度,
char_length函數:字符長度
在多字節字符集下,char(N)長度列最多可佔用的字節數爲:該字符集單字符最大
佔用字節數*N。如utf8,char(10)最多可能佔用30(3*10)個字節。

char用固定長度的存儲方式,系統爲其分配最大的存儲空間,當數據保存時,即使
沒有達到最大長度,系統也會爲其分配這麼多的存儲空間,這種存儲方式造成磁盤
空間浪費。

varchar,存儲時需要在前綴長度列表加上實際存儲的字符,該字符佔1~2個字節空間。
字符串長度<255字節時,需要1字節的空間,當大於255字節時,需要2字節空間。
對單字節latin1,char(10)佔用10個字節和varchar(10)最大佔用空間是11字節,其
中1字節來存放字符長度.

varchar和char,2種字符類型數據類型相比,差異前者是可變長度,後者是固定長度。
在存儲時,前者根據實際存儲的數據來分配最終的存儲空間,後者不管實際存儲數據
的長度,根據char規定的長度來分配存儲空間。

varchar數據類型能夠節約磁盤空間,可以提升數據庫性能,不過,也會產生一些副作用
如因其長度是可變的,爲此在數據進行更新時可能會導致一些額外的工作。如在更改前,
其字符長度是10位(varchar規定的最長字符數假設50位),此時系統就只給其分配10個存
儲的位置,更改後,其數量達到20位。由於沒有超過最大50位的限制,數據庫還是可以
存儲的。但是,其原先的存儲位置已經無法滿足其存儲的需求。此時系統需要進行額外
的操作,根據引擎不同,有的會用拆分機制,而有的會用分頁機制。

char(1)和varchar(1)這2個定義,雖然這2個只能夠用來保存單個字符,但varchar比
char多佔用一個存儲位置,因varchar數據類型時,會多用1個字節來存儲長度信息。
管理上的開銷char字符類型是沒有的。

在項目中建議:
1.字符長度判斷,如某個字段,人名,一般長度有限的,如給其分配18個字符長度即可
此時,雖然每個人的名字長度有可能不同,但在爲其分配了固定長度的字符類型,即18
個字符長度,最後浪費空間也不是很大。而如果採用varchar數據類型時,若後面需要改
名,而原先的存儲空間不足用來容納新的值,反而會造成一些額外的工作。在這種情況
下,進行均衡時,會認爲用char固定長度的數據類型更好。在實際項目中,如某個字段
的字符長度較短,我們使用固定字符長度。

2.長度是否相近,如某個字段長度比較長,但是長度總是近似的,如90個到100個字符
之間,或相同長度。較適宜用char字符類型。較典型的應用是MD5哈希值,當利用MD5哈
希值來存儲用戶密碼時,就適宜用char字符類型。此外,用戶身份證號碼等,建議用char
類型的數據

3.碎片角度進行考慮,使用char字符時,存儲空間是一次性分配的,爲此某個字段的內容
,其都是存儲在一起的。這些是不存在的碎片的。而在可變長度的字符數據類型,其存儲
長度是可變的,當其更改前後數據長度不一致時,就不可避免的會出現碎片的問題

4.varchar數據類型,分配不能過於太多,如,用戶需要存儲一個地址信息,只需要100個字符
但dba會認爲,varchar數據類型是根據實際的需要分配長度的,可以給其大一點。爲此分配
200個字符的存儲空間,那varchar(100)和varchar(200)區別?其結果是不同的,對於存儲90個
字符的數據,其存儲空間相同。但是對於內存的消耗是不同的,對與varchar數據類型來說,磁
盤上的存儲空間是根據實際字符長度來分配存儲空間的,但對於內存來說,其使用固定大小的內存
塊來保存值,就是使用字符類型中定義的長度,即200個字符空間。這對於排序或臨時表(這些內容
都需要通過內存來實現)作業會產生比較大的不利影響。對於某些字段涉及到文件排序或磁盤臨時表
時,分配varchar數據類型需要均衡,考慮冗餘,保留10%的字符長度,不能隨意分配長度,評估需要
實際長度.


補充:

MySQL中varchar最大長度是多少?
這不是一個固定的數字。本文簡要說明一下限制規則。
strlen 計算字符串長度,一箇中文當2字符
mb_strlen根據它的字符編碼模式,統計字符quot
count計算數組中的元素數目或對象中的屬性個數
 <?php
header('Content-Type:text/html;charset=UTF-8');
$string1="謝春業";//定義中文字符變量
$string2="xcy";//定義英文字符變量
//直接輸出看看他們的長度
echo strlen($string1);
echo "</br>";
echo strlen($string2);
echo "</br>";
//用 php 多字節擴展函數 mb_strlen試試看
echo mb_strlen($string1,'utf8');
echo "</br>";
echo mb_strlen($string2,'utf8');
echo "</br>";
  ?>
 輸出結果是:
9
3
3
3
1、限制規則

字段的限制在字段定義的時候有以下規則: 
a)    存儲限制
       varchar 字段是將實際內容單獨存儲在聚簇索引之外,內容開頭用1到2個字節表示實際長度(長度超過255時需要2個字節),
  因此最大長度不能超過65535。 
b)    編碼長度限制
      字符類型若爲gbk,每個字符最多佔2個字節,最大長度不能超過32766;
   字符類型若爲utf8,每個字符最多佔3個字節,最大長度不能超過21845。
   對於英文比較多的論壇 ,使用GBK則每個字符佔用2個字節,而使用UTF-8英文卻只佔一個字節。
     若定義的時候超過上述限制,則varchar字段會被強行轉爲text類型,併產生warning。 
c)    行長度限制
  導致實際應用中varchar長度限制的是一個行定義的長度。 MySQL要求一個行的定義長度不能超過65535。若定義的表長度超過這個值,則提示
  ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to    change some columns to TEXT or BLOBs。 
2、計算例子
  舉兩個例說明一下實際長度的計算。 
a)    若一個表只有一個varchar類型,如定義爲
create table t4(c varchar(N)) charset=gbk;
則此處N的最大值爲(65535-1-2)/2= 32766。

減1的原因是實際行存儲從第二個字節開始’;
減2的原因是varchar頭部的2個字節表示長度;
除2的原因是字符編碼是gbk。

b)   若一個表定義爲
create table t4(c int, c2 char(30), c3 varchar(N)) charset=utf8;
則此處N的最大值爲 (65535-1-2-4-30*3)/3=21812
減1和減2與上例相同;
減4的原因是int類型的c佔4個字節;
減30*3的原因是char(30)佔用90個字節,編碼是utf8。 
    如果被varchar超過上述的b規則,被強轉成text類型,則每個字段佔用定義長度爲11字節,當然這已經不是“varchar”了。


補充:

mysqlcharvarchar

myisam引擎中,區別,

1.char固定長度,一次性分配存儲空間;varchar變長,根據存儲字符長度分配存儲空間

2.更新很頻繁,varchar易產生碎片,因每次更新會對新的字符長度重新計算分配空間,而char不會

3.charvarchar更容易佔用更多磁盤空間

myisam中,儘量使用char數據類型,非常快(數據文件中行在磁盤上容易被找到:當按照索引中的行號查找一個行時,用行長乘以行號)。容易緩存(存儲空間固定不變),奔潰後容易重建,因爲記錄位於固定位置。因char準確計算出下一條記錄的偏移量,同時可以避免碎片存在(因頻繁更新字段的數據)

varchar,每行有一個表明行有多長的頭,因更新結果導致每行的頭長度變動,同時若一個記錄變大,它需要被分開成多片,準確定位某個記錄計算需要進過較複雜的過程;

InnoDB引擎,表的數據行內部存儲格式對固定長度的數據行和可變長度的數據行不加區分(所有數據行共用一個表頭部分,這個表頭部分存放着指向各有關數據列的指針),因char類型通常比varchar類型佔用更多存儲空間,故從減少佔用磁盤空間和磁盤IO考慮,使用varchar類型更有利;

注意,varchar還有一個問題,可以自動適應存儲空間,對節約磁盤空間有利,但是,在內存中是按照定義長度申請,長度大小對內存消耗有一定影響,所以,在varchar類型選擇上不能過分慷慨,最好根據需求均衡。


摘錄:
http://tech.it168.com/a2011/0426/1183/000001183173.shtml
MySQL技術內幕.SQL編程
發佈了20 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章