varchar 數據類型
如何理解 varchar(50)
varchar(50)
中的 50 在 mysql5.0 及以上默認是存儲的字符數,5.0 以下,默認是字節長度。
varchar 占據的存儲空間
varchar
占據的存儲空間大概有以下幾部分組成:
varchar
類型用來存儲【實際字符有多少個】這條信息的存儲空間。- 用來存儲實際字符內容的存儲空間,比如對于 utf-8 編碼,每個字符可能占用 1 - 4 個字節,實際有 3 個字符(且每個字符占 3 個字節),那么這部分要占用的存儲空間為 3 字符 x 3 字節/字符 = 9 字節。
varchar 最大支持的是 65535 個字節而不是字符
VARCHAR 能存儲的最大長度會因為你在表定義中使用的字符集不同而發生變化,以 utf-8 為例:
mysql> create table varchar_test2(col_1 varchar(65535))charset=utf8 engine=innodb;
ERROR 1074 (42000): Column length too big for column 'col_1' (max = 21845); use BLOB or TEXT insteadmysql> create table varchar_test2(col_1 varchar(21845))charset=utf8 engine=innodb;
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> create table varchar_test2(col_1 varchar(21844))charset=utf8 engine=innodb;
Query OK, 0 rows affected (0.02 sec)
因此在使用了 UTF-8 的字符集時,VARCHAR
的最大長度為 21844。
ps:我實際測下來只有最大僅支持 16383。
如何選擇合適的 varchar 字符長度
在保留一定冗余的前提下,不要給 varchar 設置過大的字符長度
雖然使用 VARCHAR (50)
和 VARCHAR (1000)
存儲‘abcd’的存儲空間開銷是一樣的,但是當你在讀取數據時,把這些數據讀取到內存的過程中,MySQL 數據庫需要分配相應大小的內存空間來存放數據。
所以更大的 VARCHAR
列在讀取時要使用更大的內存空間,即使它實際上只存儲了一丁點數據。
并且在操作這個表的過程中,如果遇到一些聚合(GROUP BY)或排序(ORDER BY)的操作,需要調用內存臨時表或磁盤臨時表時,性能會更加糟糕。
除此之外給 varchar
設置過大的字符長度還會帶來一些其他問題:
- 導致行溢出,而行溢出的數據在讀取時需要多一個 IO 操作,也會造成 InnoDB 表空間越來越大。
- InnoDB 中的大字段在做更新和刪除操作時,只能進行悲觀操作,這會造成并發性能下降。
- MySQL 中的最大行長度是 65535 字節,包含所有類型的列,因此不可能讓一個
varchar
類型的字段把空間都占了的。
補充:另外,因為 InnoDB 的數據頁默認是 16K,每個頁中至少存放 2 行數據,因此建議 VARCHAR
字段的總長度不要超過 8K。
varchar 和 text 的區別
VARCHAR
:- 存儲在
VARCHAR
類型字段中的數據是按照實際長度存儲 - 在某些情況下,
VARCHAR
可能會占用更少的存儲空間,因為它只存儲實際使用的字節數。
- 存儲在
TEXT
:TEXT
是用于存儲大塊文本數據的數據類型,可以存儲最大長度為 64KB 的數據。TEXT
類型的字段占用固定的存儲空間TEXT
數據在存儲時會進行額外的處理和管理,因此可能會有輕微的性能開銷。
總的來說,如果您需要存儲較小的文本數據,VARCHAR
可能在性能方面更優,因為它占用的存儲空間可能會較小。但是需要注意的是,當數據超過了 VARCHAR
定義的長度時,會進行截斷處理,導致部分數據丟失。
如果您需要存儲大塊的文本數據,或者數據的長度不確定,使用 TEXT
類型更為合適。TEXT
類型不會對數據進行截斷處理,并且為了性能更好地處理文本數據,還可以結合使用全文索引等技術。
參考
- https://www.imooc.com/read/88/article/2357