說明:
1、char:
固定長度的非 Unicode 字符數據,最大長度為 8,000 個字符。
2、varchar:
可變長度的非 Unicode 數據,最長為 8,000 個字符。
3、nvarchar:
可變長度 Unicode 數據,其最大長度為 4,000 字符。
4、nchar
固定長度的 Unicode 數據,最大長度為 4,000 個字符。
5、char和varchar都是字符串類型的
用Unicode編碼的字符串,結果是字符的整數值
如有以下數據結構:
工號 姓名 部門
———————–
1 張三 財務
2 李四 人事
3 王五 銷售
……..
我們定義”姓名”為char(10)(靜態)的時簡單地用php代碼表示:
簡單地模擬底層數據存儲鏈表$data
//表示每筆記錄的總長度,包括3個分隔符
實現如下:
$data="1|張三 |財務|2|李四 |人事|3|王五 |銷售|..."; //簡單地模擬底層數據存儲鏈表
//假設查找第2條記錄的"姓名"字段數據
$record_start=$col_len*1+1; //獲取第2行的起始位置
$record =substr($data,$record_start,$col_len); //獲取第2條記錄
$col_name_start=$col_num_len+2; //獲取"姓名"字段的起始位置
$col_name=substr($record,$col_name_start,$col_name_len); //獲取"姓名"字段的數據
echo $col_name;
-----------
代碼如下 復制代碼 //假設更新第2條記錄的"姓名"字段數據為"李小四"實現如下:
代碼如下 復制代碼//動態存放數據行的起始位置,數據為更新時生成(重新)
$record_1_start=1;$record_1_name_dynamic_len=4; //$col_1_name_dynamic_len記錄"姓名"動態字段的長度
$record_2_start=13;$record_2_name_dynamic_len=4;
$record_3_start=26;$record_3_name_dynamic_len=6;
...
$data="1|張三|財務|2|李四|人事|3|王小明|銷售|..."; //簡單地模擬底層數據存儲鏈表,注意存儲"姓名"的字段沒有空格
//假設查找第2條記錄的"姓名"字段數據
$record_2_end=$record_3_start-1; //獲取第2行的結束位置
$record =substr($data,$record_2_start,$record_2_end); //獲取第2條記錄
$col_name_start=$col_num_len+2; //獲取"姓名"字段的起始位置
$col_name=substr($record,$col_name_start,$record_2_name_dynamic_len); //獲取"姓名"字段的數據
echo $col_name;
//假設更新第2條記錄的"姓名"字段數據為"李小四",這邊比靜態的復雜很多
$update_info="李小四";
$update_len=strlen($update_info); //獲取更新內容的長度
if($diff_len=$update_len-$record_2_name_dynamic_len)
{
$data=substr_replace($data,"",$col_name_start,$record_2_name_dynamic_len); //清除原先數據
$record_2_name_dynamic_len=$update_len; //更新字段的長度(並存儲新值)
//在此假設總記錄數為n
for($i=2;$i<=n;$i++)
{
${'record_'.$i.'_start'}=${'record_'.$i.'_start'}+$diff_len; //重新更新每個行的起始位置(並存儲新值),系統開銷大(實際上有不同的方法解決)
}
}
$data=substr_replace($data,$update_info,$col_name_start,0);
文中直接使用”substr_replace”,而在數據量很大的時候,底層實現上的開銷也是不小的,在mysql中表現為(Row Migration)現象,在此不作贅述
根據以上的粗略實現證明:
1、varchar類型在更新環節上的系統開銷是遠大於char類型的。
2、兩者間查找搜索性能上是不相上下的。
3、兩者間的存儲數據量($data)環節上,char要顯示大於varchar。
4、大數據量提取時varchar的磁盤IO消耗更低,意味著varchar綜合查詢性能會更好。
5、沒有了。
實際應用中的結論(如在mysql中):
1、char適合字段頻繁更新時的應用。
2、varchar更節省磁盤空間。
3、實際應用中大數據量(多行)查詢返回,varchar的查詢性能比起char來要好出不少。
4、選擇char和varchar會改變整體數據結構的算法以及存儲方式。在mysql應用中,如已存在varchar字段,那麼其它所有的char字段將以varchar方式存儲。
5、沒有了。
(以上算法僅以PHP簡單描述,歡迎更好的思路加以指教)
注:此文原作者的寫作時間比較久遠了,所以有些地方和現在的有些出入,體現在:
1.在innodb引擎中,char和varchar的實現已無異,效率上並沒多大區別。
2.選擇char和varchar並不會改變整體數據結構的算法以及存儲方式。(我記得這是在MYSQL4裡的特性,網上的老文章有講述,到了MYSQL5實測已無此特性)
總結分析:
文字字段若長度固定,如:身分證號碼,就不要用 varchar 或 nvarchar,應該用 char 或 nchar。
支持多語言的站點應考慮使用 Unicode nchar 或 nvarchar 數據類型以盡量減少字符轉換問題
文字字段若長度不固定,如:地址,則該用 varchar 或 nvarchar。除了可節省存儲空間外,存取硬盤時也會較有效率