MySQL数据类型varchar详解
1.varchar(N)的逻辑意义
从MySQL 4.1开始,varchar(N)中的N指的是该字段最多能存储多少个字符(characters),不是字节数。
不管是一个中英文字符或者数字、或者一个汉字,都当做一个字符。在4.1之前,N表示的是最大存储的字节数(bytes)。
2.varchar(N)到底能存多长的数据
在MySQL reference manual上,varchar最多能存储65535个字节的数据。varchar 的最大长度受限于最大行长度(max row size,65535bytes)。65535并不是一个很精确的上限,可以继续缩小这个上限。65535个字节包括所有字段的长度,变长字段的长度标识(每个变长字段额外使用1或者2个字节记录实际数据长度)、NULL标识位的累计。
NULL标识位,如果varchar字段定义中带有default null允许列空,则需要需要1bit来标识,每8个bits的标识组成一个字段。一张表中存在N个varchar字段,那么需要(N+7)/8(取整)bytes存储所有的NULL标识位。
如果数据表只有一个varchar字段且该字段DEFAULT NULL,那么该varchar字段的最大长度为65532个字节,即65535-2-1=65532 bytes。
CREATE TABLE `vchar1` (`name` VARCHAR(65533) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `vchar2` (`name` VARCHAR(65533) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
如果数据表只有一个varchar字段且该字段NOT NULL,那么该varchar字段的最大长度为65533个字节,即65535-2=65533bytes。
CREATE TABLE `vchar3` (`name` VARCHAR(65532) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `vchar4` (`name` VARCHAR(65532) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
varchar到底能存多少个字符?这与使用的字符集相关,latin1、gbk、utf8编码存放一个字符分别需要占1、2、3个字节。
CREATE TABLE `vchar5` (`name` VARCHAR(65535) NOT NULL ) ENGINE=INNODB DEFAULT CHARSET=utf8;
Column length too big for column 'name' (max = 21845); use BLOB or TEXT instead
21845=65535/3,因为utf8编码一个字符占3个字节,varchar字段的最大长度为65533个字节,所以最多存21845个字符。
CREATE TABLE `vchar5` (`name` VARCHAR(21845) NOT NULL ) ENGINE=INNODB DEFAULT CHARSET=utf8;
Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535.
This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
因为包括字段长度标识,实际真正存的字符数是小于21845的,好好看下上面的文字说明。
gbk同理!
CREATE TABLE `vchar5` (`name` VARCHAR(65535) NOT NULL ) ENGINE=INNODB DEFAULT CHARSET=gbk;
Column length too big for column 'name' (max = 32767); use BLOB or TEXT instead
3.varchar物理存储
在物理存储上,varchar使用1到2个额外的字节表示实际存储的字符串长度(bytes)。如果列的最大长度小于256个字节,用一个字节表示(标识)。如果最大长度大于等于256,使用两个字节。
当选择的字符集为latin1,一个字符占用一个byte.
varchar(255)存储一个字符,一共使用2个bytes物理空间存储数据实际数据长度和数据值。
varchar(256)存储一个字符,使用2 bytes表示实际数据长度,一共需要3 bytes物理存储空间。
varchar对于不同的RDBMS引擎,有不通的物理存储方式,虽然有统一的逻辑意义。对于mysql的不同存储引擎,其实现方法与数据的物理存放方式也不同。
4、InnoDB中的varchar
InnoDB中varchar的物理存储方式与InnoDB使用的innodb_file_format有关。早期的innodb_file_forma使用的Antelope文件格式,支持redundant和compact两种row_format。从5.5开始或者InnoDB1.1,可以使用一种新的file format,Barracuda。Barracuda兼容Redundant,另外还支持dynamic和compressed两种row_format.
当innodb_file_format=Antelope,ROW_FORMAT=REDUNDANT 或者COMPACT。
innodb的聚集索引(cluster index)仅仅存储varchar、text、blob字段的前768个字节,多余的字节存储在一个独立的overflow page中,这个列也被称作off-page。768个字节前缀后面紧跟着20字节指针,指向overflow pages的位置。
另外,在innodb_file_format=Antelope情况下,InnoDB中最多能存储10个大字段(需要使用off-page存储)。innodbd的默认page size为16KB,InnoDB单行的长度不能超过16k/2=8k个字节,(768+20)*10 < 8k。
当innodb_file_format=Barracuda, ROW_FORMAT=DYNAMIC 或者 COMPRESSED
innodb中所有的varchar、text、blob字段数据是否完全off-page存储,根据该字段的长度和整行的总长度而定。对off-page存储的列,cluster index中仅仅存储20字节的指针,指向实际的overflow page存储位置。如果单行的长度太大而不能完全适配cluster index page,innodb将会选择最长的列作为off-page存储,直到行的长度能够适配cluster index page。
5、MyISAM中的varchar
对于MyISAM引擎,varchar字段所有数据存储在数据行内(in-line)。myisam表的row_format也影响到varchar的物理存储行为。
MyISAM的row_format可以通过create或者alter sql语句设为fixed和dynamic。另外可以通过myisampack生成row_format=compresse的存储格式。
当myisam表中不存在text或者blob类型的字段,那么可以把row_format设置为fixed(也可以为dynamic),否则只能为dynamic。
当表中存在varchar字段的时候,row_format可以设定为fixed或者dynamic。使用row_format=fixed存储varchar字段数据,浪费存储空间,varchar此时会定长存储。row_format为fixed和dynamic,varchar的物理实现方式也不同(可以查看源代码文件field.h和field.cc),因而myisam的row_format在fixed和dynamic之间发生转换的时候,varchar字段的物理存储方式也将会发生变化。
MySQL数据类型varchar详解的更多相关文章
- 【转载】MyBatis JdbcType 与Oracle、MySql数据类型对应关系详解
[原文链接]:MyBatis JdbcType 与Oracle.MySql数据类型对应关系详解 1. Mybatis JdbcType与Oracle.MySql数据类型对应列表 2. Mybatis ...
- MyBatis JdbcType 与Oracle、MySql数据类型对应关系详解
本文转自:http://blog.csdn.net/loongshawn/article/details/50496460 1. Mybatis JdbcType与Oracle.MySql数据类型对应 ...
- MySQL数据类型-decimal详解
from:http://www.linuxidc.com/Linux/2013-07/88032.htm 1.首先,对于精度比较高的东西,比如money,我会用decimal类型,不会考虑float, ...
- MariaDB(MySQL)创建、删除、选择及数据类型使用详解
一.MariaDB简介(MySQL简介略过) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行 ...
- Mysql加锁过程详解(5)-innodb 多版本并发控制原理详解
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Mysql加锁过程详解(8)-理解innodb的锁(record,gap,Next-Key lock)
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- MySQL数据库优化详解(收藏)
MySQL数据库优化详解 mysql表复制 复制表结构+复制表数据mysql> create table t3 like t1;mysql> insert into t3 select * ...
- (转)MySQL字段类型详解
MySQL字段类型详解 原文:http://www.cnblogs.com/100thMountain/p/4692842.html MySQL支持大量的列类型,它可以被分为3类:数字类型.日期和时间 ...
- MySQL EXPLAIN 命令详解
MySQL EXPLAIN 命令详解 MySQL的EXPLAIN命令用于SQL语句的查询执行计划(QEP).这条命令的输出结果能够让我们了解MySQL 优化器是如何执行SQL 语句的.这条命令并没有提 ...
随机推荐
- NIO-1缓冲区(Buffer)
import java.nio.ByteBuffer; import org.junit.Test; /* * 一.缓冲区(Buffer):在 Java NIO 中负责数据的存取.缓冲区就是数组.用于 ...
- 开源IDS系列--snorby 进程正常,但是worker无法启动 The Snorby worker is not currently running
设置页面报错: The Snorby worker is not currently running. It's imperative you start the worker immediate ...
- loadrunner场景中按scenario和group执行的区别
group:多个脚本之间按照独立设置模式跑,各个脚本可以单独设置虚拟用户.运行时间等 scenario:多个脚本之间按照相同的模式跑,将总的虚拟用户数按照一定的比例分配给各个脚本
- 更换 ECharts 散点图图标(散点图中symbol的使用)
更换 ECharts 散点图图标 使用symbol关键字
- Django学习笔记-2018.12.08
在Python的正则表达式中,有一个参数为re.S.它表示“.”(不包含外侧双引号,下同)的作用扩展到整个字符串,包括“\n”.看如下代码: import re a = '''asdfhellopas ...
- 程序员必备的代码审查(Code Review)清单
在我们关于高效代码审查的博文中,我们建议使用一个检查清单.在代码审查中,检查清单是一个非常好的工具——它们保证了审查可以在你的团队中始终如一的进行.它们也是一种保证常见问题能够被发现并被解决的便利方式 ...
- springMVC接收参数 xml/json
springMVC参数接收 作为web层框架,可以接受复杂的类型,且很简单 1.接收字符串可以直接写参数类型,参数名称,跟前端传过来的name值一样即可 如果不一样也可以,通过@RequestPara ...
- 【BZOJ 2728】 2728: [HNOI2012]与非 (线性基?)
2728: [HNOI2012]与非 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 813 Solved: 389 Description Inpu ...
- 禁用substr、substring、mid函数的sql注入脚本
#encodeing=utf-8 import requests import sys reload(sys) sys.setdefaultencoding('utf-8') payloads = l ...
- Redis 锁的实现方案
开发中不可避免的是碰到并发请求,在数据严谨性的要求不高时,我们也不需要做什么处理,但如果碰到数据严谨性非常高的时候(例如:用户金额,秒杀产品的库存...),我们就需要慎重处理了. 解决方案多种多样,下 ...