高效能MySql第三版 閱讀簡記 2

2021-10-05 02:27:26 字數 2740 閱讀 5260

varchar和char型別

varchar和char是兩種最主要的字串型別。不幸的是,很難精確地解釋這些值是怎麼儲存在磁碟和記憶體中的,因為這跟儲存引擎的具體實現有關。下面的描述假設使用的儲存引擎是innodb和/或者myisam。如果使用的不是這兩種儲存引擎,請參考所使用的儲存引擎的文件。

先看看varchar和char值通常在磁碟上怎麼儲存。請注意,儲存引擎儲存char或者varchar值的方式在記憶體中和在磁碟上可能不一樣,所以mysql伺服器從儲存引擎讀出的值可能需要轉換為另一種儲存格式。下面是關於兩種型別的一些比較。

varchar

varchar型別用於儲存可變長字串,是最常見的字串資料型別。它比定長型別更節省空間,因為它僅使用必要的空間(例如,越短的字串使用越少的空間)。有一種情況例外,如果mysql表使用row_format=fixed建立的話,每一行都會使用定長儲存,這會很浪費空間。

varchar需要使用1或2個額外位元組記錄字串的長度:如果列的最大長度小於或等於255位元組,則只使用1個位元組表示,否則使用2個位元組。假設採用latin1字符集,乙個varchar(10)的列需要11個位元組的儲存空間。

varchar(1000)的列則需要1002個位元組,因為需要2個位元組儲存長度資訊。varchar節省了儲存空間,所以對效能也有幫助。但是,由於行是變長的,在update時可能使行變得比原來更長,這就導致需要做額外的工作。如果乙個行占用的空間增長,並且在頁內沒有更多的空間可以儲存,在這種情況下,不同的儲存引擎的處理方式是不一樣的。例如,myisam會將行拆成不同的片段儲存,innodb則需要**頁來使行可以放進頁內。其他一些儲存引擎也許從不在原資料位置更新資料。

下面這些情況下使用varchar是合適的:字串列的最大長度比平均長度大很多;列的更新很少,所以碎片不是問題;使用了像utf-8這樣複雜的字符集,每個字元都使用不同的位元組數進行儲存。

在5.0或者更高版本,mysql在儲存和檢索時會保留末尾空格。但在4.1或更老的版本,mysql會剔除末尾空格。

char

char型別是定長的:mysql總是根據定義的字串長度分配足夠的空間。當儲存char值時,mysql會刪除所有的末尾空格(在mysql 4.1和更老版本中varchar也是這樣實現的——也就是說這些版本中char和varchar在邏輯上是一樣的,區別只是在儲存格式上)。char值會根據需要採用空格進行填充以方便比較。

char適合儲存很短的字串,或者所有值都接近同乙個長度。例如,char非常適合儲存密碼的md5值,因為這是乙個定長的值。對於經常變更的資料,char也比varchar更好,因為定長的char型別不容易產生碎片。對於非常短的列,char比varchar在儲存空間上也更有效率。例如用char(1)來儲存只有y和n的值,如果採用單位元組字符集(5)只需要乙個位元組,但是varchar(1)卻需要兩個位元組,因為還有乙個記錄長度的額外位元組。

char型別的這些行為可能有一點難以理解,下面通過乙個具體的例子來說明。

首先,我們建立一張只有乙個char(10)欄位的表並且往裡面插入一些值:

mysql> create table char_test( char_col char(10));

mysql> insert into char_test(char_col) values-> ('string1'), (' string2'), ('string3 ')

當檢索這些值的時候,會發現string3末尾的空格被截斷了。

如果用varchar(10)字段儲存相同的值,可以得到如下結果(6):

資料如何儲存取決於儲存引擎,並非所有的儲存引擎都會按照相同的方式處理定長和變長的字串。memory引擎只支援定長的行,即使有變長字段也會根據最大長度分配最大空間(7)。不過,填充和擷取空格的行為在不同儲存引擎都是一樣的,因為這是在mysql伺服器層進行處理的。

一般來說:用的比較多的是varchar:因為庫中儲存的資料大多都是不定長的,而varchar可以根據資料長度而使用不同的空間,只不過要多使用乙個位元組用來記錄字串長度;

char一般是用來儲存字典的code值(男或女,地區**之類)/表中的id值; 因為這些資料的長度是1位/32/或者固定的幾位.

另乙個例子是乙個ipv4位址。人們經常使用varchar(15)列來儲存ip位址。然而,它們實際上是32位無符號整數,不是字串。用小數點將位址分成四段的表示方法只是為了讓人們閱讀容易。所以應該用無符號整數儲存ip位址。mysql提供inet_aton()和inet_ntoa()函式在這兩種表示方法之間轉換。

例如:測試用例:

select inet_aton('172.25.43.55') from demo_test_del;

得到值:

2887330615

select  inet_ntoa(2887330615) from demo_test_del;

得到值:

172.25.43.55

附錄:

(5) 記住字串長度定義不是位元組數,是字元數。多位元組字符集會需要更多的空間儲存單個字元。

(6) string3尾部的空格還在。——譯者注

(7) percona server裡的memory引擎支援變長的行。

高效能MySql第三版 閱讀簡記 1

mysql支援的資料型別非常多,選擇正確的資料型別對於獲得高效能至關重要。不管儲存哪種型別的資料,下面幾個簡單的原則都有助於做出更好的選擇。更小的通常更好。一般情況下,應該盡量使用可以正確儲存資料的最小資料型別 1 更小的資料型別通常更快,因為它們占用更少的磁碟 記憶體和cpu快取,並且處理時需要的...

高效能mysql第三版

高效能mysql第三版 本書目錄結構如下 第一章 mysql架構與歷史 1.1 mysql邏輯架構 1.2 開發控制 1.3 事務 1.4 多版本併發控制 1.5 mysql的儲存引擎 1.6 mysql時間線 timeline 1.7 mysql的開發模式 第二章 mysql基準測試 2.1 為什...

編譯apue 第三版

想要直接使用作者提供的源 就需要編譯下,這個檔名是src.3e.tar.gz 很簡單的幾步就搞定了.解壓src.3e.tar.gz 進入apue.3e make 進入apue.3e lib目錄,複製libapue.a到 usr local lib目錄 進入 apue.3e include目錄,複製 ...