MySQL中varchar最大長度是多少

一. varchar存儲規則:

4.0版本以下,varchar(20),指的是20字節,如果存放UTF8漢字時,只能存6個(每個漢字3字節)?
5.0版本以上,varchar(20),指的是20字符,無論存放的是數字、字母還是UTF8漢字(每個漢字3字節),都可以存放20個,最大大小是65532字節?

二. varchar和char 的區別:

char是一種固定長度的類型,varchar則是一種可變長度的類型,它們的區別是: char(M)類型的數據列里,每個值都占用M個字節,如果某個長度小于M,MySQL就會在它的右邊用空格字符補足.(在檢索操作中那些填補出來的空格字符將被去掉)在varchar(M)類型的數據列里,每個值只占用剛好夠用的字節再加上一個用來記錄其長度的字節(即總長度為L+1字節).?

在MySQL中用來判斷是否需要進行對據列類型轉換的規則

1、在一個數據表里,如果每一個數據列的長度都是固定的,那么每一個數據行的長度也將是固定的.

2、只要數據表里有一個數據列的長度的可變的,那么各數據行的長度都是可變的.

3、如果某個數據表里的數據行的長度是可變的,那么,為了節約存儲空間,MySQL會把這個數據表里的固定長度類型的數據列轉換為相應的可變長度類型.例外:長度小于4個字符的char數據列不會被轉換為varchar類型
?
?
?ps :被問到一個問題:MySQL中varchar最大長度是多少?這不是一個固定的數字。本文簡要說明一下限制規則。

1、限制規則

字段的限制在字段定義的時候有以下規則:

a) 存儲限制

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 byte。
mysql> create table t1 ( name varchar(65532) default null)charset=latin1;
Query OK, 0 rows affected (0.09 sec)mysql> 
mysql> create table t2 ( name varchar(65533) default null)charset=latin1;  
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
mysql> 

可以看見當設置長度為65533時,已經超過行最大長度,我們可以計算一下,行最大長度是65535字節。上面t2表name字段使用varchar(65533),字符集是latin1,占用1個字節。還有默認為空,那么還有null標識位,( 1 + 7 ) / 8 =1,所以null標識位占用1個字節。現在我們來看看,65533 + 1 + 2=65536字節,已經大于行最大長度。這里2字節怎么來的???因為varchar類型存儲變長字段的字符類型,與char類型不同的是,其存儲時需要在前綴長度列表加上實際存儲的字符,當存儲的字符串長度小于255字節時,其需要1字節的空間,當大于255字節時,需要2字節的空間。

如果數據表只有一個varchar字段且該字段NOT NULL,那么該varchar字段的最大長度為65533個字節,即65535-2=65533byte
mysql> create table t2 ( name varchar(65533) not null) charset=latin1;   
Query OK, 0 rows affected (0.03 sec)mysql> 
mysql> create table t3 ( name varchar(65534) not null) charset=latin1;  
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
mysql> 
b) 編碼長度限制

字符類型若為gbk,每個字符最多占2個字節,最大長度不能超過32766;

字符類型若為utf8,每個字符最多占3個字節,最大長度不能超過21845。

若定義的時候超過上述限制,則varchar字段會被強行轉為text類型,并產生warning。
?

c) 行長度限制

導致實際應用中varchar長度限制的是一個行定義的長度。?MySQL要求一個行的定義長度不能超過65535。若定義的表長度超過這個值,則提示

ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs。

2、計算例子

舉兩個例說明一下實際長度的計算。

a) ?若一個表只有一個varchar類型,如定義為

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

則此處N的最大值為(65535-1-2)/2=?32766。

減1的原因是實際行存儲從第二個字節開始;

減2的原因是varchar頭部的2個字節表示長度;

除2的原因是字符編碼是gbk。
?

b) 若一個表定義為

create table t4(c int, c2 char(30), c3 varchar(N)) charset=utf8;

則此處N的最大值為?(65535-1-2-4-30*3)/3=21812

減1和減2與上例相同;

減4的原因是int類型的c占4個字節;

減30*3的原因是char(30)占用90個字節,編碼是utf8。
?
如果被varchar超過上述的b規則,被強轉成text類型,則每個字段占用定義長度為11字節,當然這已經不是varchar了。
?
則此處N的最大值為?(65535-1-2-4-30*3)/3=21812,例子如下:
mysql> create table t4(c int, c2 char(30), c3 varchar(21812)) charset=utf8; 
Query OK, 0 rows affected (0.05 sec)mysql> 
mysql> create table t5(c int, c2 char(30), c3 varchar(21813)) charset=utf8;  
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
mysql> 

?

最后讓我們來看一個例子

復制代碼
CREATE TABLE t6 (
id int,
a VARCHAR(100) DEFAULT NULL,
b VARCHAR(100) DEFAULT NULL,
c VARCHAR(100) DEFAULT NULL,
d VARCHAR(100) DEFAULT NULL,
e VARCHAR(100) DEFAULT NULL,
f VARCHAR(100) DEFAULT NULL,
g VARCHAR(100) DEFAULT NULL,
h VARCHAR(100) DEFAULT NULL,
i VARCHAR(N) DEFAULT NULL
) CHARSET=utf8;                                                                                                                                                                                                                   
復制代碼

那么上面這條語句中的varchar(N)的最大值是多少呢?

讓我們來計算一下

每個NULL字段用1bit標識,10個字段都是default null,那么需要用(10+7)/8bit = 2 bytes存儲NULL標識位。int占用4個 byte。

(65535 - 1 - 2*8 ?-4 - 100*3*8 -2)/3=21037

mysql> CREATE TABLE t6 ( id int, a VARCHAR(100) DEFAULT NULL, b VARCHAR(100) DEFAULT NULL, c VARCHAR(100) DEFAULT NULL, d VARCHAR(100) DEFAULT NULL, e VARCHAR(100) DEFAULT NULL, f VARCHAR(100) DEFAULT NULL, g VARCHAR(100) DEFAULT NULL, h VARCHAR(100) DEFAULT NULL, i VARCHAR(21037) DEFAULT NULL ) CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)mysql> 
mysql> CREATE TABLE t7 ( id int, a VARCHAR(100) DEFAULT NULL, b VARCHAR(100) DEFAULT NULL, c VARCHAR(100) DEFAULT NULL, d VARCHAR(100) DEFAULT NULL, e VARCHAR(100) DEFAULT NULL, f VARCHAR(100) DEFAULT NULL, g VARCHAR(100) DEFAULT NULL, h VARCHAR(100) DEFAULT NULL, i VARCHAR(21038) DEFAULT NULL ) CHARSET=utf8;  
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
mysql> 

?可以看見多一個字符都報錯了。

varchar到底能存多少個字符?這與使用的字符集相關,latin1、gbk、utf8編碼存放一個字符分別需要占1、2、3個字節。

?

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字段的物理存儲方式也將會發生變化。

?

參考資料:

http://dev.mysql.com/doc/refman/5.5/en/column-count-limit.html

<<MySQL技術內幕--InnoDB引擎第二版>>

作者:Atlas

出處:Atlas的博客?http://www.cnblogs.com/gomysql

您的支持是對博主最大的鼓勵,感謝您的認真閱讀。本文版權歸作者所有,歡迎轉載,但請保留該聲明。如果您需要技術支持,本人亦提供有償服務。

分類:?MySQL

轉載于:https://www.cnblogs.com/canger/p/9850727.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/250392.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250392.shtml
英文地址,請注明出處:http://en.pswp.cn/news/250392.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

bzoj 1232: [Usaco2008Nov]安慰奶牛cheer【最小生成樹】

有趣 每條邊在算答案的時候被算了二倍的邊權值加上兩個端點的權值&#xff0c;然后睡覺點額外加一次 所以可以用這個權做MST&#xff0c;然后加上點權最小的點 #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N1…

JavaScript --- [學習筆記]觀察者模式 理解對象 工廠模式 構造函數模式

說明 本系列(JS基礎梳理)為后面TCP的模擬實現做準備本篇的主要內容: 觀察者模式、工廠模式、構造函數模式 和 對對象的理解 1. 觀察者模式 參考JavaScript設計模式 1.1 消息注冊方法 “將訂閱者注冊的消息推入到消息隊列中” [算法思路] : 在推入到消息隊列時,如果此消息…

java_day19_MVC和配置文件

簡單的MVC設計 MVC的全名是Model View Controller&#xff0c;是模型(model)&#xff0d;視圖(view)&#xff0d;控制器(controller)的縮寫&#xff0c;是一種軟件設計典范。它是用一種業務邏輯、數據與界面顯示分離的方法來組織代碼&#xff0c;將眾多的業務邏輯聚集到一個部件…

Problem I: 打印金字塔

#include<stdio.h> int main() {int n,i,j,k;scanf("%d",&n);for(i1;i<n;i){for(j1;j<n-i;j)printf(" ");for(k1;k<2*i-1;k)printf("*");printf("\n");}return 0; } HINT 用雙重循環做&#xff0c;外循環代表行數&…

webpack --- 發布環境的配置 代碼壓縮 代碼分類

說明 源代碼本篇主要對發布環境的配置說明前面2點是對webpack的一個復習.第3點開始,逐步配置部署代碼 1. Webpack發布的策略 2.1 在實際開發中,一般會有兩套方案: 開發期間的項目:包含了測試文件、測試數據、開發工具、測試工具等相關配置,有利于項目的開發和測試,但是這些文…

salesforce lightning零基礎學習(三) 表達式的!(綁定表達式)與 #(非綁定表達式)

在salesforce的classic中&#xff0c;我們使用{!expresion}在前臺頁面展示信息&#xff0c;在lightning中&#xff0c;上一篇我們也提及了&#xff0c;如果展示attribute的值&#xff0c;可以使用{!v.expresion}展示信息。 lightning在component中解析動態值的時候&#xff0c;…

sqlserver學習3---sql函數

一、SQL DML 和 DDL 可以把 SQL 分為兩個部分&#xff1a;數據操作語言 (DML) 和 數據定義語言 (DDL)。 SQL (結構化查詢語言)是用于執行查詢的語法。但是 SQL 語言也包含用于更新、插入和刪除記錄的語法。 查詢和更新指令構成了 SQL 的 DML 部分&#xff1a; SELECT - 從數據庫…

JavaScript --- [學習筆記] 原型模式

說明 接JavaScript — > [學習筆記]觀察者模式 & 理解對象 & 工廠模式 & 構造函數模式上一篇構造函數模式創建的實例,不同實例的同一個方法是不相等的,為了解決這個問題.出現了原型模式 1. 原型模式 具體做法是,不在構造函數中定義對象實例的信息,而是將這些…

網絡協議各層概述

網絡協議概述 OSI是一個開放性的通信系統互連參考模型&#xff0c;他是一個定義得非常好的協議規范。OSI模型有7層結構&#xff0c;每層都可以有幾個子層。 OSI的7層從上到下分別是 7 應用層 6 表示層 5 會話層 4 傳輸層 3 網絡層 2 數據鏈路層 1 物理層&#xff1b; 其中高層&…

A start job is running for Raise network interface(5min 13s )問題解決方法

命令&#xff1a;sudo vim /etc/systemd/system/network-online.target.wants/networking.service將里面的TimeoutStartSec5min 修改為TimeoutStartSec2sec 然后重啟系統&#xff0c;就可以生效了&#xff0c;開機速度很快 轉載于:https://www.cnblogs.com/sea-stream/p/98615…

javascript --- 實現對象的深拷貝

淺拷貝和深拷貝 淺拷貝: 只拷貝一層.當對象是復雜數據類型(Object、 Array)時,只拷貝引用深拷貝: 多層拷貝.復雜數據類型,會重新分配內存空間. 實現淺拷貝的2種方法 使用for ... in 實現 var obj {name: marron,age: 18,msg: {sex: "1" } } var o {}; for(let …

Qt與FFmpeg聯合開發指南(二)——解碼(2):封裝和界面設計

與解碼相關的主要代碼在上一篇博客中已經做了介紹&#xff0c;本篇我們會先討論一下如何控制解碼速度再提供一個我個人的封裝思路。最后回歸到界面設計環節重點看一下如何保證播放器界面在縮放和拖動的過程中保證視頻畫面的寬高比例。 一、解碼速度 播放器播放媒體文件的時候播…

Bzoj1051 受歡迎的牛

每一頭牛的愿望就是變成一頭最受歡迎的牛。現在有 N 頭牛&#xff0c;給你 M 對整數 (A,B)&#xff0c;表示牛 A 認為牛 B 受歡迎。這種關系是具有傳遞性的&#xff0c;如果 A 認為 B 受歡迎&#xff0c;B 認為 C 受歡迎&#xff0c;那么牛 A 也認為牛 C 受歡迎。你的任務是求出…

node --- 模塊加載機制

1. Node.js中模塊加載機制 1.1 模塊查找規則-當模塊擁有路徑但沒有后綴時 require(./find.js); require(./find);require方法根據模塊路徑查找模塊,如果是完整路徑,直接進入模塊如果模塊后綴省略,先找同名JS文件再找同名JS文件夾 require(./find); // 以上會先找到命令行目錄…

51Nod 蜥蜴和地下室(搜索)

哈利喜歡玩角色扮演的電腦游戲《蜥蜴和地下室》。此時&#xff0c;他正在扮演一個魔術師。在最后一關&#xff0c;他必須和一排的弓箭手戰斗。他唯一能消滅他們的辦法是一個火球咒語。如果哈利用他的火球咒語攻擊第i個弓箭手&#xff08;他們從左到右標記&#xff09;&#xff…

多線程——實現Runnable接口實現一個多線程

實現Runnable接口實現一個多線程 Runnable接口源碼&#xff1a; package java.lang; //Runnable接口源碼只有一個run方法 public interface Runnable {public abstract void run(); } 實現Runnable的兩個多線程類&#xff1a; public class RunnableThread1 implements Runnabl…

javascript --- 文件上傳即時預覽 閉包實現多圖片即時預覽

使用javascript原生功能實現,點擊上傳文件,然后再網頁上顯示出來 1. 初級顯示 1.1 準備一個input標簽和一個img標簽 <input typefile id"file"> <img id"preview" src"">1.2 js代碼如下 // 將上傳的圖片顯示到頁面上function sho…

第一次作業:深入Linux源碼分析進程模型

一.進程的概念 第一&#xff0c;進程是一個實體。每一個進程都有它自己的地址空間&#xff0c;一般情況下&#xff0c;包括文本區域&#xff08;text region&#xff09;、數據區域&#xff08;data region&#xff09;和堆棧&#xff08;stack region&#xff09;。文本區域存…

關于模型驗證那點事兒

今天應笑笑老師之問&#xff0c;做了一個模型驗證的例子&#xff0c;發現之前對這個東西的理解太片面&#xff0c;重新整理了一下思路 字段驗證優先級高于類驗證 什么是類驗證呢&#xff1f;就是兩個字段組合的驗證&#xff0c;比如你Admin不允許修改密碼&#xff0c;你修改密碼…

mongoose --- createUser

說明 源代碼記錄、遺忘回顧mongoDB默認不需要使用賬號密碼即可訪問數據庫.下面是給mongoDB添加超級管理員和普通用戶的方法 以系統管理員的方式運行powershell連接數據庫 mongo查看數據庫: show dbs切換到admin數據庫: use admin創建超級管理員賬戶: db.createUser({user: roo…