mysql中char、varchar、nvarchar数据类型的用法区别

说明:
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

 代码如下 复制代码
$col_num_len  =1;      //工号长度为1
$col_name_len=10;    //姓名长度为10
$col_unit_len   =4;     //部门长度为4
$col_len=$col_num_len+$col_name_len+$col_unit_len+3;       

  //表示每笔记录的总长度,包括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条记录的"姓名"字段数据为"李小四"
$update_info="李小四";
$data=substr_replace($data,$update_info,$col_name_start,$col_name_len);        //更新字段,流程结束
而如果我们定义”姓名”字段为varchar(10)(动态)的时候情况则要复杂:
注意存储”姓名”的字段没有空格,这是char和varchar的存储区别
$col_num_len  =1;      //工号长度为1
$col_name_len=10;    //姓名长度为10
$col_unit_len   =4;     //部门长度为4
$col_len=$col_num_len+$col_name_len+$col_unit_len+3;

实现如下:

 代码如下 复制代码

//动态存放数据行的起始位置,数据为更新时生成(重新)
$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。除了可节省存储空间外,存取硬盘时也会较有效率

时间: 2024-11-01 00:48:10

mysql中char、varchar、nvarchar数据类型的用法区别的相关文章

mysql中char(1)为什么能输入1个汉字啊?

问题描述 mysql中char(1)为什么能输入1个汉字啊? 为什么我设置表中的性别为char(1) 结果可以输入1个汉字啊?求解 解决方案 MYSQL的编码用的是UTF-8,而UTF-8是一种变长的编码方式.它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度. 并不是说只有1个字节

mysql中模糊查询的四种用法介绍_Mysql

下面介绍mysql中模糊查询的四种用法: 1,%:表示任意0个或多个字符.可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示. 比如 SELECT * FROM [user] WHERE u_name LIKE '%三%' 将会把u_name为"张三","张猫三"."三脚猫","唐三藏"等等有"三"的记录全找出来. 另外,如果需要找出u_name中既有"三"又有

mysql中模糊查询的四种用法介绍

下面介绍mysql中模糊查询的四种用法: 1,%:表示任意0个或多个字符.可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示. 比如 SELECT * FROM [user] WHERE u_name LIKE '%三%' 将会把u_name为"张三","张猫三"."三脚猫","唐三藏"等等有"三"的记录全找出来. 另外,如果需要找出u_name中既有"三"又有

mysql中engine=innodb和engine=myisam的区别介绍

MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持,本文为大家讲解下mysql中engine=innodb和engine=myisam的区别,不懂的朋友可以学习下,希望对大家有所帮助   最开始用MySQL Administrator建数据库的时候,表缺省是InnoDB类型,也就没有在意.后来用Access2MySQL导数据的时候发现只能导成 MyISAM类型的表,不知道这两种类型有什么区别,就去查了查.原来是MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持. My

mysql中order by与group by的区别

以下是对mysql中order by与group by的区别进行了详细的分析介绍,需要的朋友可以过来参考下   order by 从英文里理解就是行的排序方式,默认的为升序. order by 后面必须列出排序的字段名,可以是多个字段名.      group by 从英文里理解就是分组.必须有"聚合函数"来配合才能使用,使用时至少需要一个分组标志字段.  什么是"聚合函数"?  像sum().count().avg()等都是"聚合函数"  使用

MySQL中create table as 与like的区别分析_Mysql

本文分析了MySQL中create table as 与like的区别.分享给大家供大家参考,具体如下: 对于mysql的复制相同表结构方法,有create table as 和create table like 两种,区别是什么呢? 复制代码 代码如下: create table t2 as select * from t1 where 1=2;或者 复制代码 代码如下: limit 0; as创建出来的t2表(新表)缺少t1表(源表)的索引信息,只有表结构相同,没有索引. 复制代码 代码如下

MySQL中char和varchar有啥区别?优缺点是啥?

在mysql教程中char与varchar的区别呢,都是用来存储字符串的,只是他们的保存方式不一样罢了,char有固定的长度,而varchar属于可变长的字符类型. char与varchar的区别  char (13)长度固定, 如'www.jb51.net' 存储需要空间 12个字符:  varchar(13) 可变长 如'www.jb51.net' 需要存储空间 13字符: 从上面可以看得出来char 长度是固定的,不管你存储的数据是多少他都会都固定的长度.而varchar则处可变长度但他要

MySQL中CHAR和VARCHAR类型演变和详解_Mysql

一.演变: MySQL数据库的varchar类型在5.0.3以下的版本中的最大长度限制为255,其数据范围可以是0~255. 在MySQL5.0.3及以上的版本中,varchar数据类型的长度支持到了65535,也就是说可以存放65532个字节的数据,起始位和结束位占去了3个字节,也就是说,在5.0.3以下版本中需要使用固定的TEXT或BLOB格式存放的数据可以在高版本中使用可变长的varchar来存放,这样就能有效的减少数据库文件的大小. 如果在varchar中写入大于设定的长度,默认情况下会

mysql中char与varchar的区别

在mysql教程中char与varchar的区别呢,都是用来存储字符串的,只是他们的保存方式不一样罢了,char有固定的长度,而varchar属于可变长的字符类型. char与varchar的区别 char (13)长度固定, 如'www.111cn.net'  存储需要空间 13个字符 varchar(13) 可变长 如'www.111cn.net'  需要存储空间 14字符, 从上面可以看得出来char 长度是固定的,不管你存储的数据是多少他都会都固定的长度.而varchar则处可变长度但他