Char属于固定长度的字符类型,而varchar属于可变长的字符类型。

下表将各种字符串值保存到char(4)varchar4)列后的结果,说明了charvarchar之间的差别

Char(4)

存储需求

Varchar (4)

存储需求

‘’

‘     ’

4字符节

‘’

1字符节

‘ab’

‘ab   ’

4字符节

‘ab ’

3字符节

‘abcd’

‘abcd’

4字符节

‘abcd’

5字符节

‘abcdefgh’

‘abcd’

4字符节

‘abcd’

5字符节

请注意,最后一行的值只适用于非“严格模式”时,如果mysql运行在严格模式,超过列长度的值将不会保存,并且会出现错误提示。

         char(4)varchar(4)列检索的值并不总是相同,因为检索事从char列删除了尾部的空格。

         由于char是固定长度的,所以他的处理速度比varhcar快的多,但是其缺点是浪费存储空间,程序需要对尾行空格进行处理,所以对于哪些长度变化不大并且对查询速度要求较高的数据可以考虑使用char类型存储

         另外,随着mysql版本的不断升级,varchar数据类型的性能也在不断改进并提高,所以在许多应用中,varvhar类型被更多使用

         mysql中,不同的存储引擎对charvarchar的使用原则有所不同,这里简单概括若下:

  Myisam存储引擎:建议使用固定长度的数据列代替可变长的数据列

  Memory存储引擎:目前都使用固定长度的数据行存储,因此无论使用char varchar列都没有关系,两者都是作为char类型处理

  Innodb存储引擎:建议使用varchar类型。对于innodb数据表,内部的行存储格式没有区分固定长度和可变长度列(所有数据行都使用指向数据列值的头指针),因此在本质上,使用固定长度的char列不一定比使用可变长度varchar的性能要好,因此,主要的性能因素是数据行使用的存储总量,由于char平均占用的空间多于varchar,因此使用varchar来最小化需要处理的数据行的存储总量和磁盘I/O是比较好的。

上面来自网易《深入浅出MYSQL数据库开发、优化与管理维护》

以下是测试过程,针对MYISAM,5.5.19 MySQL Community Server (GPL):

表结构

 

插入100万条记录

DELIMITER $$

USE `test`$$

DROP PROCEDURE IF EXISTS `test1`$$

CREATE DEFINER=`admin`@`%` PROCEDURE `test1`()
BEGIN
    DECLARE i INT DEFAULT 1;
   
    WHILE i <= 1000000 DO
   
    INSERT INTO test1 VALUES (i,i,'abc');
   
    SET i=i+1;
   
    END WHILE;
  
    END$$

DELIMITER ;

 

DELIMITER $$

USE `test`$$

DROP PROCEDURE IF EXISTS `test2`$$

CREATE DEFINER=`admin`@`%` PROCEDURE `test2`()
BEGIN
    DECLARE i INT DEFAULT 1;
   
    WHILE i <= 1000000 DO
   
    INSERT INTO test2 VALUES (i,i,'abc');
   
    SET i=i+1;
   
    END WHILE;
  
    END$$

DELIMITER ;

[root@vm01 test]# ll -h |grep test
-rw-rw---- 1 mysql mysql 8.5K 04-01 17:16 test1.frm
-rw-rw---- 1 mysql mysql  19M 04-01 17:20 test1.MYD
-rw-rw---- 1 mysql mysql  17M 04-01 17:20 test1.MYI

-rw-rw---- 1 mysql mysql 8.5K 04-01 17:16 test2.frm
-rw-rw---- 1 mysql mysql  20M 04-01 17:26 test2.MYD
-rw-rw---- 1 mysql mysql  12M 04-01 17:26 test2.MYI

char表数据+主键+索引=19M+17M=36M

varchar表数据+主键+索引=20M+12M=32M

=====================================================================

下面测试不带索引的。

插入100万条记录

-rw-rw---- 1 mysql mysql 8.5K 04-01 17:44 test1.frm
-rw-rw---- 1 mysql mysql  19M 04-01 18:01 test1.MYD
-rw-rw---- 1 mysql mysql 9.8M 04-01 18:01 test1.MYI

-rw-rw---- 1 mysql mysql 8.5K 04-01 17:44 test2.frm
-rw-rw---- 1 mysql mysql  20M 04-01 18:04 test2.MYD
-rw-rw---- 1 mysql mysql 9.9M 04-01 18:04 test2.MYI

char表数据+主键=19M+9.8M=28.8M

varchar表数据+主键=20M+9.9M=29.9M

 

=====================================================================

下面测试不带主键和索引的。

 

插入100万条记录

[root@vm01 test]# ll -h | grep test
-rw-rw---- 1 mysql mysql 8.5K 04-01 18:08 test1.frm
-rw-rw---- 1 mysql mysql  19M 04-01 18:10 test1.MYD
-rw-rw---- 1 mysql mysql 1.0K 04-01 18:10 test1.MYI

-rw-rw---- 1 mysql mysql 8.5K 04-01 18:08 test2.frm
-rw-rw---- 1 mysql mysql  20M 04-01 18:11 test2.MYD
-rw-rw---- 1 mysql mysql 1.0K 04-01 18:11 test2.MYI

char表数据=19M

varchar表数据=20M

=====================================================================

总结:针对MYISAM引擎,如果使用varchar字符类型,增加索引的容量要小于不加索引的。