一個關於mysql中varchar的問題

來源:互聯網
上載者:User
為什麼很多人喜歡在 MySQL 中使用 VARCHAR(255) ?

回複內容:

為什麼很多人喜歡在 MySQL 中使用 VARCHAR(255) ?

1、曆史原因

varchar在MySQL 5.0.3之前只支援0-255byte,在MySQL 5.0.3之後才支援到0-65535byte

這裡的255是字元的長度

2、varchar的最大長度

看一段代碼

mysql> show variables like '%col%';+---------------------------+-----------------+| Variable_name             | Value           |+---------------------------+-----------------+| collation_connection      | utf8_general_ci || collation_database        | utf8_general_ci || collation_server          | utf8_general_ci || protocol_version          | 10              || slave_compressed_protocol | OFF             |+---------------------------+-----------------+5 rows in set (0.00 sec)mysql> show char set;  +----------+-----------------------------+---------------------+--------+| Charset  | Description                 | Default collation   | Maxlen |+----------+-----------------------------+---------------------+--------+| big5     | Big5 Traditional Chinese    | big5_chinese_ci     |      2 || dec8     | DEC West European           | dec8_swedish_ci     |      1 || cp850    | DOS West European           | cp850_general_ci    |      1 || hp8      | HP West European            | hp8_english_ci      |      1 || koi8r    | KOI8-R Relcom Russian       | koi8r_general_ci    |      1 || latin1   | cp1252 West European        | latin1_swedish_ci   |      1 || latin2   | ISO 8859-2 Central European | latin2_general_ci   |      1 || swe7     | 7bit Swedish                | swe7_swedish_ci     |      1 || ascii    | US ASCII                    | ascii_general_ci    |      1 || ujis     | EUC-JP Japanese             | ujis_japanese_ci    |      3 || sjis     | Shift-JIS Japanese          | sjis_japanese_ci    |      2 || hebrew   | ISO 8859-8 Hebrew           | hebrew_general_ci   |      1 || tis620   | TIS620 Thai                 | tis620_thai_ci      |      1 || euckr    | EUC-KR Korean               | euckr_korean_ci     |      2 || koi8u    | KOI8-U Ukrainian            | koi8u_general_ci    |      1 || gb2312   | GB2312 Simplified Chinese   | gb2312_chinese_ci   |      2 || greek    | ISO 8859-7 Greek            | greek_general_ci    |      1 || cp1250   | Windows Central European    | cp1250_general_ci   |      1 || gbk      | GBK Simplified Chinese      | gbk_chinese_ci      |      2 || latin5   | ISO 8859-9 Turkish          | latin5_turkish_ci   |      1 || armscii8 | ARMSCII-8 Armenian          | armscii8_general_ci |      1 || utf8     | UTF-8 Unicode               | utf8_general_ci     |      3 || ucs2     | UCS-2 Unicode               | ucs2_general_ci     |      2 || cp866    | DOS Russian                 | cp866_general_ci    |      1 || keybcs2  | DOS Kamenicky Czech-Slovak  | keybcs2_general_ci  |      1 || macce    | Mac Central European        | macce_general_ci    |      1 || macroman | Mac West European           | macroman_general_ci |      1 || cp852    | DOS Central European        | cp852_general_ci    |      1 || latin7   | ISO 8859-13 Baltic          | latin7_general_ci   |      1 || utf8mb4  | UTF-8 Unicode               | utf8mb4_general_ci  |      4 || cp1251   | Windows Cyrillic            | cp1251_general_ci   |      1 || utf16    | UTF-16 Unicode              | utf16_general_ci    |      4 || utf16le  | UTF-16LE Unicode            | utf16le_general_ci  |      4 || cp1256   | Windows Arabic              | cp1256_general_ci   |      1 || cp1257   | Windows Baltic              | cp1257_general_ci   |      1 || utf32    | UTF-32 Unicode              | utf32_general_ci    |      4 || binary   | Binary pseudo charset       | binary              |      1 || geostd8  | GEOSTD8 Georgian            | geostd8_general_ci  |      1 || cp932    | SJIS for Windows Japanese   | cp932_japanese_ci   |      2 || eucjpms  | UJIS for Windows Japanese   | eucjpms_japanese_ci |      3 |+----------+-----------------------------+---------------------+--------+40 rows in set (0.00 sec)mysql> create database testdbx DEFAULT CHARACTER SET latin1;mysql> use testdb;Database changedmysql> use testdbx;Database changedmysql> drop table  if exists testa;create table testa (name varchar(65532));mysql> drop table  if exists testa;create table testa (name varchar(65533));Query OK, 0 rows affected (0.01 sec)ERROR 1118 (42000): 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 BLOBsmysql> drop table  if exists testa;create table testa (name varchar(65533) not null);

總結如下

name varchar(100) not null will be 1 byte (length) + up to 100 chars (latin1) name varchar(500) not null will be 2 bytes (length) + up to 500 chars (latin1) name varchar(65533) not null will be 2 bytes (length) + up to 65533 chars (latin1) name varchar(65532) will be 2 bytes (length) + up to 65532 chars (latin1) + 1 null byte 

mysql的vachar欄位的類型雖然最大長度是65535,但是並不是能存這麼多資料,最大可以到65533(不允許非空欄位的時候),當允許非空欄位的時候只能到65532

3、varchar實體儲存體

在實體儲存體上,varchar使用1到2個額外的位元組表示實際儲存的字串長度(bytes)。如果列的最大長度小於256個位元組,用一個位元組表示(標識)。如果最大長度大於等於256,使用兩個位元組。

當選擇的字元集為latin1,一個字元佔用一個byte

varchar(255)儲存一個字元,使用2bytes物理空間儲存資料實際資料長度和資料值。

varchar(256)儲存一個字元,使用2bytes表示實際資料長度,一共需要3bytes實體儲存體空間。

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欄位的實體儲存體方式也將會發生變化。

總結 :

1、儲存2^8 = 256 / overflow pages / 曆史原因

3、varchar不一定比char慢

3、如果有大欄位使用text,請拆表

4、varchar建立索引的時候,前面20個字元以內即可

5、其實該怎麼用還要怎麼用 varchar(30) 、 vachar(300)等

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

反正varchar是可變長度的,佔用的空間比char()小,而且最大也就255字元(英文或中文具體看字元集而定)

習慣了吧,以前舊系統有個256位元組的上限,很多人養成了這個習慣。新系統上限遠大於這個,所以建議在新系統中就老老實實按整數算就好了,你最多希望使用者輸入的字元不超過300就寫300,200就寫200,完全沒有必要弄個255,搞得使用者很茫然。

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.