mysql建表长度的限制

在mysql建表时,出现以下报错信息:

错误一:行大小过大,所使用的表这种类型的最大的行大小,不算BLOB类型,是65535。(这是我翻译的)

   原因是MySQL在建表的时候有个限制:MySQL要求一个行的定义长度不能超过65535。具体的原因可以看:

http://dev.mysql.com/doc/refman/5.1/en/silent-column-changes.html

  1. 单个字段如果大于65535,则转换为TEXT。
  2. 单行最大限制为65535,这里不包括TEXT、BLOB。 

按照上面总结的限制,来解释出现的现象:

单个字段长度:varchar(10000) ,字节数:10000*3(utf8)+() = 30002 ,小于65535,可以建立。

这里为什么用2呢?

因为在varchar中,需要用1-2个字节来标识这一列的长度。如果此列值要求不超过255字节,就用1字节;如果值可能需要超过255字节,就用2个字节(参看下文A column uses one length byte if values require no more than 255 bytes,two length bytes if values may require more than 255 bytes.),而此处显然超过255字节的范围,所以用2。

单行记录长度:varchar(10000)*3,字节数:30000*3(utf8)+(2*3) = 90006,大于65535,不能建立,所以报错。

 错误二:列areaShow的长度太大,最大只能为21845。

21845怎么算出来的呢?请看下解:

mysql中varchar最大长度是多少?

一、限制规则:

字段的限制在字段定义的时候有以下规则:

  1. 存储限制:varchar字段是将实际内容单独存储在聚簇索引(?)之外,内容开头用1到2个字节表示实际长度(长度超过255时需要2个字节),因此最大长度不能超过65535
  2. 编码长度限制:字符集类型若为gbk,每个字符最多占2个字节,最大长度不能超过;字符集类型若为utf8,每个字符最多占3个字节,最大长度不能超过。若定义的时候超过上述限制,则varchar字段会被强行转为text类型,并产生warning(应为直接报错)。
  3. 行长度限制:导致实际应用中varchar长度限制的是一个行定义的长度。 MySQL要求一个行的定义长度不能超过65535。若定义的表长度超过这个值,则报错。

二、计算例子(阐述32766,以及21845是怎么计算出来的?

①字符集类型若为gbk,每个字符最多占2个字节,最大长度不能超过32766。

a)若一个表只有一个varchar类型,如定义为

create table t4(c varchar(N)) charset=gbk;

则此处N的最大值为(65535-1-2)/2= 32766。

为什么-1?

因为表中varchar字段的定义default NULL,由于是default null,要占用一个额外的字节存储标识。如果NOT NULL,最大可以存储65533bytes的数据。

具体查看大神pythian(我也不知道是谁)的解释(我也没看过):

http://www.pythian.com/blog/text-vs-varchar/

减2的原因是varchar头部的2个字节表示长度;

除2的原因是字符编码是gbk。

②字符集类型若为utf8,每个字符最多占3个字节,最大长度不能超过21845

   疑问:我怎么计算出来21844了?

若一个表只有一个varchar类型,如定义为

create table tb_test (
var varchar(M) default null
) engine=innoDB default charset=utf8;

则此处N的最大值为(65535-1-2)/3= 21844(怎么可能为21845呢?)。

除3的原因是字符编码是utf8。

而且我也试验了一下,如下:

 这是一个很大的疑问???

下文转自zhengwish的专栏

http://blog.csdn.net/zhengwish/article/details/50774049

深深觉得这篇文章解决了我一些困惑,特记之,感谢zhengwish

对这varcharchar这两个数据类型最简单区分是:varchar存放变长字符串char存放定长字符串。那么它们是否还有其他差别呢?本文将从浅显的层次以抛出问题解决问题的形式对两者的区分进一步了解。

首先我们确认一下mysql版本。本文中的所有知识点都基于mysql5.0+,本文中的例子基于mysql5.6。

那么,接下来开始抛出我的问题。

问题一:varchar(m),char(n)里面的m或n代表的是字节还是字符的个数?

为了得到答案,我们打开mysql手册,看到这样一句话The CHAR and VARCHAR types are declared with a length that indicates the maximum number of  characters  you want to store. For example, CHAR(30) can hold up to 30 characters.

注意描红的单词,手册中明确指出,存放的是字符的个数。

问题二:varchar(m),char(n)里面的m和n是否有长度限制?分别是多少?

首先我们明确一下,m和n是一定会有长度限制的。那么究竟是多少呢?这个问题需要我们详细看一下各个知识点。

第一:讨论char(n)

The length of a CHAR column is fixed to the length that you declare when you create the table. The length can be any value from 0 to 255. When CHAR values are stored, they are right-padded with spaces to the specified length.When CHAR values are retrieved, trailing spaces are removed unless the PAD_CHAR_TO_FULL_LENGTH [581]SQL mode is enabled.

手册中指出,长度的限制是0-255,经过验证,长度的限制是0-255个字符。也就是说,没有明确标出字节的限制数。

第二:讨论varchar(m)

Values in VARCHAR columns are variable-length strings. The length can be specified as a value from 0 to 65,535.The effective maximum length of a VARCHAR is subject to the maximum row size (65,535 bytes, which is shared among all columns) and the character set used. See Section E.10.4, “Table Column-Count and Row-Size Limits”.

In contrast to CHAR, VARCHAR values are stored as a 1-byte or 2-byte length prefix plus data. The length prefix indicates the number of bytes in the value. A column uses one length byte if values require no more than 255 bytes,two length bytes if values may require more than 255 bytes.

注意上面两段话中的描红部分。

首先我们明确,m也是字符的个数。而上面句子中提到的65535是指varchar列最大可存放的字节数。

我们知道,在gbk编码格式下,字节数=字符数*2 ;在utf8编码格式下,字节数=字符数*3。

但是,在varchar中,因为是变长,所以需要1-2个字节来标识这一列的长度。如果varchar字段定义中带有default null允许列空,则需要1bit来标识,每8个bits的标识组成一个字段。一张表中存在N个varchar字段,那么需要(N+7)/8 (取整)bytes存储所有的NULL标识位。

我们假设一张表只有varchar一列,且此时该字段设置为DEFAULT NULL,那么该varchar字段的最大长度为65535-2-(1+7)/8 = 65532bytes。

这时候新的疑问出现了。为什么要假设表只有一列数据,这是很不符合常规的。原因在上面描紫的语句。

什么意思?

我们要知道,每一行数据的总长度是有限制的,每一行最大字节数就是65535个。我们创建一张表时,需要把每个字段需要占用的字节进行统计,总数不能超过65535即可。其中text和blob根据存放的数据量不同可能占用1,2,3,4个字节。在计算的时候要按4字节进行计算。

问题三:使用myisam和Innodb引擎对varchar和char的选择应该怎么考虑?

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

memory存储引擎 目前都使用固定数据行存储,因此无论使用char varchar列都没关系。

innodb 存储引擎 建意使用varchar 类型。

本文补充:

在mysql中,函数LENGTH(s)函数返回字符串的字节长度。使用utf-8(UNICODE的一种变长字符编码,又称为万国码)编码字符集时,一个汉字是2个字节、一个数字或者字母为一个字节。

char_length:返回字符串所占的字符数,不管汉字还是数字或者是字母都算是一个字符。

本文参考以及建议阅读:

   

http://dev.mysql.com/doc/refman/5.1/en/silent-column-changes.html
http://dev.mysql.com/doc/refman/5.1/en/column-count-limit.html

http://ourmysql.com/archives/702

http://www.cnblogs.com/doit8791/archive/2012/05/28/2522556.html
http://blog.csdn.net/dyllove98/article/details/9289483
http://lobert.iteye.com/blog/1647844
http://blog.csdn.net/yunhua_lee/article/details/7038780
http://blog.sina.com.cn/s/blog_5461c7ff0100ugd1.html
http://www.jb51.net/article/23575.htm

浅谈mysql中varchar(m)与char(n)的区别与联系的更多相关文章

  1. 浅谈MySQL中优化sql语句查询常用的30种方法 - 转载

    浅谈MySQL中优化sql语句查询常用的30种方法 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使 ...

  2. 浅谈HTTP中GET和POST请求方式的区别

    浅谈HTTP中GET和POST请求的区别 HTTP认知: HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议.HTTP的底层是TCP/IP.所以GET和POST的底层也是TCP/IP,也 ...

  3. 浅谈mysql中utf8和utf8mb4区别

    转自:http://ourmysql.com/archives/1402  实践过程中发现有时mysql的字符集会引起故障,所以需要了解下这个知识点. 一.简介 MySQL在5.5.3之后增加了这个u ...

  4. 浅谈MySQL中优化sql语句查询常用的30种方法

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索 ...

  5. Mysql 性能优化7【重要】sql语句的优化 浅谈MySQL中优化sql语句查询常用的30种方法(转)

    原文链接   http://www.jb51.net/article/39221.htm 这篇文章大家都在转载,估计写的有条理吧,本人稍微做一下补充 1.对查询进行优化,应尽量避免全表扫描,首先应考虑 ...

  6. 浅谈 MySQL 中优化 SQL 语句查询常用的 30 种方法

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索 ...

  7. 辛星浅谈mysql中的数据碎片以及引擎为MyISAM下的操作

    对于mysql中的数据碎片,事实上和我们删除数据是息息相关的,删除数据的时候必定会在数据文件里造成不连续的空白空间,对于少量的数据的删除,并不会产生多少的空白空间.假设在一段时间内的大量的删除操作,会 ...

  8. 浅谈mysql中不同事务隔离级别下数据的显示效果

    事务的概念 事 务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查 询语句因为崩溃或其他原因而无法执行,那 ...

  9. 浅谈mysql中各种表空间(tablespaces)的概念

    mysql中,会涉及到各种表空间的概念,虽然,很多方面这些概念和Oracle有相似性,但也有很多不同的地方,初学者很容易被这些概念弄的晕头转向,从而,混淆这些概念的区别和理解,下面,就简要介绍和说明一 ...

随机推荐

  1. java环境中基于jvm的两大语言:scala,groovy

    一.java环境中基于jvm的两大语言:scala,groovy 可以在java项目里混编这两种语言: scala:静态语言,多范式语言,糅合了面向对象.面向过程:可以与java和net互操作:融汇了 ...

  2. Linux android开发环境问题:Unexcepted exception:cannot run program "android-sdk-linux/platfor-tools/adb" :err=2,No such file or directory.

    出现这个问题的原因: 我的linux是64位 ,而adb目前只有32位的,所以要安装运行32的环境. 不同的linux系统需要安装的不同: 我的Centos  解决方案如下 其他linux操作系统(参 ...

  3. Pintos修改优先级捐赠、嵌套捐赠、锁的获得与释放、信号量及PV操作

    Pintos修改优先级捐赠.嵌套捐赠.锁的获得与释放.信号量及PV操作 原有的优先级更改的情况下面没有考虑到捐赠的情况,仅仅只是改变更改了当前线程的优先级,更别说恢复原本优先级了,所以不能通过任何有关 ...

  4. Daily Scrum7

    今天我们小组开会内容分为以下部分: part 1: 研讨上一届的项目里积分制度的功能,确定其不足,以及我们可以改进的地方: part 2: 讨论确定我们项目的积分制度的功能目标: part 3:针对用 ...

  5. MVC4 网站发布(整理 + 部分转载 + 部分问题收集和解决方案)

    网站发布步骤: 这部分是转载文章 在此标明出处,以前有文章是转的没标明的请谅解,因为有些已经无法找到出处,或者与其它原因. 如有冒犯请联系本人,或删除,或标明出处. 因为好的文章,以前只想收藏,但连接 ...

  6. 【BZOJ】【3504】【CQOI2014】危桥

    网络流/最大流 比较裸的最大流= = 无向图上走来回其实就等价与走两遍>_> 如果路径有相交其实不影响答案的 比较恶心的是两个人路过同一座桥,但走的方向不同互相抵消流量了…… 其实只要在第 ...

  7. 来自平时工作中的javascript知识的积累---持续补充中

    ① SeaJs和RequireJS最大的区别 解惑:来自豆友 ② javascript中如何判断undefined var exp = undefined; if (exp === undefined ...

  8. 在linux中使用phpize安装php扩展模块

    介绍:linux系统中,php安装成功后,在bin目录下会生成一个名叫phpize的可执行脚本,这个脚本的用途是动态安装php扩展模块.使用phpize脚本安装php扩展模块的好处:在安装php时没有 ...

  9. thinkPHP生成静态分页列表

    改造分页类Pagehtml.class.php <?php // 静态分页列表类 class Pagehtml extends Think { //分页url public $pageUrl; ...

  10. Linux VPS 免费管理面板推荐

    现在各种国内外VPS,云主机横行,越来越多的站长接受在VPS上建站,很多VPS主机售价便宜,性能优秀,但都是基于linux系统的,如openvz的主机,linux服务器系统主要是通过shell命令行来 ...