varchar类型字段为什么经常定义成255

MySQL | ver < 4.1: VARCHAR以字节为单位存储,所以假设全部为常用汉字(UTF-8

3字节编码长度),则VARCHAR(255)共可存放约85个汉字;

MySQL | ver >= 4.1:

VARCHAR以字符为单位存储,假设输入仍然为常用汉字,则VARCHAR(255)可以存放255个汉字。 

另外,据我所知,MySQL对UTF-8的支持也仅仅限于1~3字节编码长度(Unicode:0x0000~0xFFFF),可以满足大部分需求,但是生僻字就不行了。

那么VARCHAR的最大值是多少呢?

根据官方文档,VARCHAR 最多可以是 65535 字节(这也意味着一条记录只有这一个字段,因为 MySQL 一行只能包含 65535 字节)。

然而,无法为这么长的 VARCHAR 做索引,对于 MyISAM,可以对前 1000 个字节做索引,对于 InnoDB,则只有 767 字节。(来源依据)

在varchar长度接近256时,varchar长度设置成255的好处:

1、方便InnoDB建索引,对于 MyISAM,可以对前 1000 个字节做索引,对于 InnoDB,则只有 767 字节。(来源依据)。255X3=765

2、少申请一个字节,记录字符创长度,一个8位的tinyint,可以表示的无符号数值的范围是,0-255,如果长度超过了255,需要在申请个字节


1.MySQL建立索引时假设没有限制索引的大小,索引长度会默认採用的该字段的长度。也就是说varchar(20)和varchar(255)相应的索引长度分别为20*3(utf-8)(+2+1),255*3(utf-8)(+2+1)。当中"+2"用来存储长度信息,“+1”用来标记是否为空。载入索引信息时用varchar(255)类型会占用很多其它的内存; (备注:当字段定义为非空的时候。是否为空的标记将不占用字节)

比如。測试sql(InnoDB引擎)例如以下:

CREATE DATABASE TestDataBase

USE TestDataBase

CREATE TABLE ABC (

  `id` int(11) DEFAULT NULL,

  `name` varchar(20) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8

ALTER  TABLE  `ABC`  ADD  INDEX `nameIndex` (`name`)

explain select name from ABC

alter table ABC  modify name varchar(255)

explain select name from ABC

结果中的ken_len表示索引使用的字节数:

key_len的长度计算公式:

varchr(10)变长字段且同意NULL:10*(Character Set:utf8=3,gbk=2,latin1=1)+1(NULL)+2(变长字段)

varchr(10)变长字段且不同意NULL:10*(Character Set:utf8=3,gbk=2,latin1=1)+2(变长字段)

char(10)固定字段且同意NULL:10*(Character Set:utf8=3,gbk=2,latin1=1)+1(NULL)

char(10)固定字段且同意NULL:10*(Character Set:utf8=3,gbk=2,latin1=1)

依据这个值。就能够推断索引使用情况,特别是在组合索引的时候,推断全部的索引字段都被查询用到。

2.varchar(20)与varchar(255)都是保持可变的字符串,当使用ROW_FORMAT=FIXED创建MyISAM表时,会为每行使用固定的长度空间,这样设置不同的varchar长度值时。存储相同数据所占用的空间是不一样。

通常情况下使用varchar(20)和varchar(255)保持'hello'占用的空间都是一样的,但使用长度较短的列却有巨大的优势。较大的列使用很多其它的内存。由于MySQL一般会分配固定大小的内存块来保存值,这对排序或使用基于内存的暂时表尤其不好。相同的事情也会发生在使用文件排序或者基于磁盘的暂时表的时候。


很多时候我们看到一些表字符串类型的字段定义为varchar(255),开始以为varchar只能定义为255这个长度值,其实不然。

官方文档所说,varchar有效的最大长度取决于行的容量,以及用的字符集,整行的所有列的定义长度不能超过65535字节(bytes),text、blob等大字段类型除外,

P.S. https://dev.mysql.com/doc/refman/5.7/en/char.html

《小白学习MySQL - 变通创建索引的案例一则》提到了,

InnoDB,如果需要建索引,就不能超过767bytes,utf8编码,255*3=765 bytes,是能建索引情况下的最大值,utf8mb4编码,默认字符长度则应该是767除以4向下取整,就是191。如果设置了innodb_large_prefix,最大长度是3072字节,utf8编码,1024*3=3072 bytes,utf8mb4编码,768*4=3072。

MyISAM,如果需要建索引,就不能超过1000bytes,utf8编码,333*3=999 bytes,是能建索引情况下的最大值,utf8mb4编码,默认字符长度则应该是1000除以4,就是250。

一般情况下,我们用的是InnoDB引擎,utf8则是常用字符集,因此varchar类型字段定义为255比较合适。

但实际上,varchar(255)并不是最优的字符定义长度,究竟定成多少,还是要根据实际需求来决定,例如这个字段我就不需要创建索引,定义超过255,是可以的,只能说255是常规情况下较少出错的一个值。


有没有觉得我们设置varchar长度的时候,很多时候都设置成255,这是为什么呢?

其实是因为在5.5.3版本之前

InnoDB存储引擎的表索引的前缀长度最长是767字节(bytes),

MyIsam存储引擎的表索引的前缀长度最长是1000字节(bytes)。

所以如果字段要创建索引的话,长度就不能超过对应存储引擎的要求 767 bytes或 1000 bytes,而如果中文按1个字符占用3个字节计算,总字节数刚好为765。

1071 - Specified key was too long; max key length is 767 bytes

要控制字节长度,就要说到字节编码了。

一、位(bit)、字节(byte)、字符

位(bit):计算机内部数据储存的最小单位,10001000是一个八位二进制数。

字节(byte):计算机中数据处理 的基本单位,习惯上用大写 B 来表示。

1 B = 8bit

1 KB = 1024 B

1 MB = 1024 KB (2^10 B)

1 GB = 1024 MB (2^20 B)

1 TB = 1024 GB (2^30 B)

字符:计算机中使用的字母、数字、字和符号,如 a、A、中、+、*、の......

二、编码

UTF-8:是用以解决国际上字符的一种多字节编码。包含全世界所有国家需要用到的字符,是国际编码,通用性强。一个汉字 = 3个字节,英文是一个字节

UTF-8编码的文字可以在各国支持UTF8字符集额的浏览器上显示。如果是UTF8编码,则在外国人的英文IE也能显示中文,他们无需下载IE的中文语言支持包。

GBK:GB2312基础上扩容后的国家标准,兼容GB2312。

GBK的文字编码是用双字节来表示的,即不论中、英文字符均使用双字节来表示,为了区分中文,将其最高位都设定成1。

GBK包含全部中文字符,是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBK大。

utf8mb4:在MySQL5.5.3之后增加的,专门用来兼容四字节的unicode的utf-8的超集,比utf-8能表示更多的字符。mb4即为most bytes 4。

latin1:ISO-8859-1的别名,单字节编码,在支持Latin1编码的系统中传输和存储其他任何编码的字节流都不会被抛弃。换言之,把其他任何编码的字节流当作Latin1编码看待都没有问题

三、中文与编码

MySql 5.0 以上的版本:

一个汉字占多少长度与编码有关:

UTF-8:一个汉字 = 3个字节,英文 = 1个字节

GBK: 一个汉字 = 2个字节,英文 = 1个字节

varchar(n) 在mysql 5.0.3之前表示n个字节,之后修改为表示n个字符,无论汉字和英文,mySql都能存入n个字符,仅实际字节长度有所区别。

MySQL检查长度,可用一下SQL语言查询

SELECT LENGTH(fieldname) FROM tablename

测试

(1)测试 UTF-8

CREATE TABLE `test_char_length_utf8` (

`v1` varchar(9) ,

`v2` varchar(9)

)ENGINE=InnoDB CHARSET=utf8;

创建表单(UTF-8)

SELECT LENGTH(v1), LENGTH(v2) FROM test_char_length_utf8

查询长度

(2)测试 GKB

CREATE TABLE `test_char_length_gbk` (

`v1` varchar(9) ,

`v2` varchar(9)

)ENGINE=InnoDB CHARSET=gbk;

创建表单(GBK)

SELECT LENGTH(v1), LENGTH(v2) FROM test_char_length_gbk

查询长度

四、总结

varchar(255) 是为了索引而设置,能够存储255个汉字。

varchar(255) 后来成为一些人使用的惯性,其实应根据实际业务场景设置长度。

varchar(n) 中的n在mysql 5.0.3之前表示n个字节,之后表示n个字符,按照实际使用的数据库字符编码集,占用不同字节数量,比如GBK、UTF8MB4等等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/433134.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

对于网络IO的理解

网络IO理解 首先服务端将本机地址和端口bind在listensock上&#xff0c;再用listen()去将listensock套接字设置为listen状态&#xff0c;然后调用accept&#xff0c;进入阻塞状态。如果此时有客户端请求连接&#xff0c;就是第一次握手的开始。 客户端会先调用connect来申请连…

牛客网 华为机试 提前不重复的整数

本题要求提取不重复的整数&#xff0c;然后倒序输出&#xff0c;我们可以采用hashset来存储结果&#xff0c;这样就能避免重复。 为了从右往左获取数字&#xff0c;我们可以把这个数对10取余&#xff0c;得到的余数就是其每一位的数。然后我们把得到的数字添加到hashset中&…

#QT(MP3播放器-部分界面)

1.IDE&#xff1a;QTCreator 2.实验&#xff1a;制作一个mps播放器&#xff0c;界面可以实现鼠标拖动 3.记录&#xff1a; &#xff08;1&#xff09;network网络多线程 &#xff08;2&#xff09;Http &#xff08;3&#xff09;QJsonObject封装JSON对象 &#xff08;4&am…

c语言-大小写字母的转换

目录 方法一&#xff1a;库函数直接转换 1、toupper的测试代码 2、tolower的测试代码 方法二&#xff1a;通过修改ASCII码值转换 1、自己实现大写转小写 2、自己实现小写转大写 结语 前言&#xff1a; 在使用c语言写代码时&#xff0c;通常会遇到很多将大小写字母相互…

性能测试总结 —— 测试流程篇!

本文主要介绍下性能测试的基本流程&#xff0c;性能测试从实际执行层面来看&#xff0c;测试的过程一般分为这么几个阶段&#xff0c;如下图&#xff1a;       下面分别介绍下每个阶段具体需要做什么&#xff1a; 一、性能需求分析&#xff1a; 性能需求分析是整个性能…

从零学习Linux操作系统 第三十部分 部署Anisble

一、ansible实验环境的部署 主控机 更改服务器主机名 hostnamectl set-hostname westos_ansible.westos.org 主服务器需要能够实现上网 修改网卡使之能够上网 能ping通 代表可以连接外网 搭载本地软件仓库 并且挂载镜像 装载 dnf install httpd -y 让其开机启动并且…

C语言指针的初步认识--学习笔记(3)

1. 字符指针变量 在C语言中&#xff0c;字符串通常被视为字符数组&#xff0c;但它们可以有不同的表示方式。字符指针变量存储的是字符串的地址。这意味着&#xff0c;当你有一个字符串时&#xff0c;你可以通过改变字符指针的值来改变这个字符串&#xff0c;因为你实际上改变的…

C++_位图

目录 1、位图的使用 2、位图实现 3、位图与哈希表的区别 4、位图的应用 结语 前言&#xff1a; 位图采用的是哈希表的思想&#xff0c;哈希表的映射层面是在字节上&#xff0c;而位图的映射层面就是在bit位上。由于bit位所能展现的信息无非只有‘1’和‘0’&#xff0c;所…

LeetCode 热题 100 (尽量ACM模式刷) 持续更新!!!

LeetCode 热题 100 哈希hash 1 两数之和 /** 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出和为目标值target的那两个整数&#xff0c;并返回它们的数组下标。* 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案…

项目管理必备:进度报告撰写指南!

本文将探讨如何将进度报告写作整合到你的工作流程中&#xff0c;包括确定最适合的报告时间、编写方法和与团队一起构建报告结构的建议。最后&#xff0c;还会分享一些撰写进度报告的最佳做法&#xff0c;助你掌握这种对工作有巨大帮助的方法。 什么是进度报告&#xff1f; 它…

Python 应用程序编程接口库之pywin32使用详解

概要 在Python的世界里,有许多优秀的第三方库可以帮助开发者更轻松地处理各种任务。其中,pywin32库是一个特别引人注目的工具,它提供了对Windows API的完整访问,使得开发者能够利用Python来编写强大的Windows应用程序,从简单的脚本到复杂的桌面应用,pywin32都能胜任。 什…

算力调度和云计算有何区别

Canalys发布的研究报告显示&#xff0c;2023年第二季度&#xff0c;全球云基础设施服务支出增长16%&#xff0c;达到724亿美元。 此前云厂商们的高速增长&#xff0c;主要归功于大规模的企业数字化转型和上云。当前市场的增速放缓&#xff0c;除了上云普及带来的市场增量见顶&…

Dockerfile(3) - WORKDIR 指令详解

WORKDIR 切换到镜像中的指定路径&#xff0c;设置工作目录在 WORKDIR 中需要使用绝对路径&#xff0c;如果镜像中对应的路径不存在&#xff0c;会自动创建此目录一般用 WORKDIR 来替代 切换目录进行操作的指令 RUN cd <path> && <do something> WORKDIR…

【算法】顺时针打印矩阵(图文详解,代码详细注释

目录 题目 代码如下: 题目 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则打印出数字:1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10 这一道题乍一看,没有包含任何复杂的数据结构和…

Yolov8改进交流

YOLO v8改进 YOLOv8的改进&#xff0c;我接触的主要分为网络改进和代码改进&#xff0c;网络改进就是以注意力、主干为主&#xff0c;代码改进就是类似于Iou&#xff0c;类别权重等修改。 以下是yolov8的原始模型。 # Ultralytics YOLO &#x1f680;, AGPL-3.0 license # YO…

词嵌入向量和位置编码向量的整合

词嵌入向量和位置编码向量的整合 flyfish 文本序列 -> 输入词嵌入向量&#xff08;Word Embedding Vector&#xff09;-> 词向量 位置编码向量&#xff08;Positional Encoding Vector&#xff09; Embedding 的维度使用了3 可以输出打印看结果 from collections im…

如何使用Python操作MySQL的各种功能?高级用法?

当今互联网时代&#xff0c;数据处理已经成为了一个非常重要的任务。而MySQL作为一款开源的关系型数据库&#xff0c;被广泛应用于各种场景。本篇博客将介绍如何使用Python操作MySQL的各种功能&#xff0c;以及一些高级用法。 连接MySQL 在Python中&#xff0c;我们可以使用p…

不同用户同时编辑商品资料导致的db并发覆盖

背景 这个问题的背景来源于有用户反馈&#xff0c;他在商品系统中对商品打的标签不见了&#xff0c;影响到了前端页面上商品的资料显示 不同用户编辑同一商品导致的数据覆盖问题分析 查询操作日志发现用户B确实编辑过商品资料&#xff0c;并且日志显示确实打上了标签&#x…

【论文阅读】Mamba:选择状态空间模型的线性时间序列建模(二)

文章目录 3.4 一个简化的SSM结构3.5 选择机制的性质3.5.1 和门控机制的联系3.5.2 选择机制的解释 3.6 额外的模型细节A 讨论&#xff1a;选择机制C 选择SSM的机制 Mamba论文 第一部分 Mamba:选择状态空间模型的线性时间序列建模(一) 3.4 一个简化的SSM结构 如同结构SSM&#…

C++入门项目:通讯录管理系统

文章目录 一、步骤拆分1.系统需求2.显示菜单3.添加联系人4.显示联系人5.删除联系人6.查找联系人7.修改联系人8.清空通讯录9.退出功能 二、完整代码&#xff08;200行&#xff09;三、手把手视频教程 一、步骤拆分 1.系统需求 利用C来实现一个通讯录管理系统&#xff0c;系统中…