mysql的char,varchar,text,blob是幾個有聯繫可是有有很大區別的字段類型,這算是mysql的基礎吧,但是基礎沒有學好,惡補一下。 php
先簡單的總結一下: mysql
char:定長,最大255個字符 算法
varchar:變長,最大65535個字符(既是單列的限制,又是整行的限制) sql
text:變長,有字符集的大對象,並根據字符集進行排序和校驗,大小寫不敏感 數據庫
blob:變長,無字符集的二進制大對象,大小寫敏感 spa
如下只是我我的的理解,才疏學淺,望各路高人指點。 code
我使用的引擎是myisam,因此如下的探討是集中在myisam上的。 對象
首先解釋char,char是項目中經常使用的字段類型之一,它表明的含義是採用固定長度存儲數據,換句話說,數據初始化的是就爲該類型的字段分配固定長度的存儲空間,即便沒有達到存儲空間的長度,實際佔用的存儲空間也是定義時的長度。舉個例子來講,好比某字段 a char(50),指定的長度是50個字符的存儲空間,那麼當你存入一個字符:「abc」的時候,實際上字符長度是3個字符,可是佔用的硬盤空間仍是50個字符。很顯然,char的缺點就出來了:浪費存儲空間!可是同時char的優勢也顯示出來了:固定長度,(索引)效率極高,不存在碎片。 blog
這裏咱們再探討一下char的存儲方式,雖然char會浪費極大的存儲空間,可是你想過對於字符串的先後空格char是如何處理的嗎?當存儲的字符串沒有達到char的最大長度時,字符串後面是不會以空格來填充的,並且char會過濾字符串末端的空格而後存儲,而在比較字符串的時候又會自動空格填充到字符串的末端。 排序
好了,對char有了瞭解之後,對varchar的理解也就容易了。
varchar是存儲可變長度的字符串,簡單的說咱們定義表機構的時候指定的字段長度是最大長度,當字符串沒有達到最大長度的時候以字符串的實際長度來存儲的,不佔用多餘的存儲空間。所以,通常狀況下,varchar比char節省存儲空間,可是也常常有例外,後面接着探討這個問題。
一個特殊的狀況是建立表的時候採用ROW_FORMAT=FIXED選項(默認的是ROW_FORMAT=DYNAMIC),那麼mysql就會爲每行數據分配固定長度的存儲空間,固然這是特例。不知道你有沒有想過:爲何有管理員願意這樣作呢?對varchar分配固定長度的存儲空間是有道理的。舉一個常見的例子,假設採用DYNAMIC默認選項,那麼咱們建立一個字段b varchar(100),如今咱們插入一個只有10個字符的數據:abcdefghij,很好,只佔用了10個字符的空間,相比char節省了很多存儲空間。可是你想到問題了嗎?好比某天之後你發現這個字段須要更新一下,更新爲20個字符的數據:abcdefghijklmnopqrst,你知道數據庫該如何存儲嗎?原先的存儲位置分配的只有10個字符的空間,如今要存儲20個字符,小於長度限制(最大長度是100個字符),問題就來了,mysql會如何處理呢?這裏接下來可能要探討mysql存儲層面的分頁機制或者拆分機制,就再也不繼續深刻了。總之不管mysql採起什麼方式,確定會在磁盤上造成碎片,長此以往造成的磁盤碎片對系統效率是一個致命的打擊,因此咱們常常看到有管理員要把mysql導出而後導入,就是爲了解決這個問題,提升效率。
上面咱們提出來了一個問題:varchar比char節省存儲空間,可是也常常有例外!對於這個疑問咱們如何理解呢?要深刻分析這個問題,咱們須要再次深刻了解varchar的存儲機制。經常使用的中文存儲通常採用gbk或者utf-8兩種字符集,gbk每一個字符佔2個字節,utf-8每一個字符佔3個字節,因此:gbk字符集的最大存儲長度是
(65535-1-1)/2= 32766或者(65535-1-2)/2= 32766,這個算法的含義是:65535是varchar的最大長度,第一個-1表示實際存儲位置是從第二位開始的,第二個-1或者-2表明的含義是:varchar 字段是將實際內容單獨存儲在聚簇索引以外,內容開頭用1到2個字節表示實際長度(長度小於255時用1個字節,長度超過255時須要2個字節),除以2的緣由是一個gbk字符集的字符佔2個字節長度,因此根據狀況能夠得出gbk字符集的最大存儲長度是32766。
那麼UTF-8字符集呢?算法以下:
(65535-1-1)/3= 21844或者(65535-1-2)/3= 21844減1減2的含義同上,除以3的含義是一個utf-8的字符集字符佔用實際長度是3個字節。
看完了這段你就能理解char(1)和varchar(1)佔用的存儲空間了吧?在這個極端狀況下,很顯然char更節省存儲空間,由於char沒有管理數據的額外開銷。
接下來,咱們重點探討一下varchar的65535存儲長度表明的真正含義是什麼?由於前面說過一句話:既是單列的限制,又是整行的限制!咱們詳細來解釋一下。對於單列的限制,咱們舉一個例子:create table tablename(c varchar(N)) charset=gbk;那麼N的最大值是(65535-1-2)=32766。同時,若是同一個有其餘字段的話,那麼全部字段的長度和不能超過65535,舉個例子:create table tablename(c1 int(4), c2 char(30), c3 varchar(N) ) charset=utf8,那麼N的最大值是(65535-1-2-4-30*3)/3=21812,也許你很理解int(4)須要4個字符的位置,這裏可能須要更深刻的瞭解int的存儲機制,我不太瞭解,書尚未看呢。總之int類型佔用4個字符的長度,換句話說create table tablename(c1 int(32), c2 char(30), c3 varchar(N) ) charset=utf8,N的最大值也是(65535-1-2-4-30*3)/3=21812。我作了一個簡單的實驗,看截圖。
第一張varchar的長度大於21812,因而失敗了
第二張varchar長度等於21812,保存成功
轉載請註明來源:www.blogguy.cn
廢話了這麼多,總之一句話:char在浪費存儲空間的劣勢下,得到了較高的效率,varchar相反。接下來咱們也要總結一下什麼狀況下使用char,什麼狀況下使用varchar。
原則一:根據字符串長度肯定,凡是固定長度的字符串或者相似固定長度的字符串一概用char。好比身份證號碼,手機號碼,銀行卡號,MD5,哈希值等這是字符串是固定長度的,毫無疑問用char,還有一類是基本固定長度可是略有出入的,好比中國人的姓名等,通常長度多是2~5個漢字,這類信息也很是適合用char來存儲,只要分配一些略大於一般長度便可。
原則二:數據是否常常更改致使碎片,可能常常變更而產生存儲碎片的小字符串一概用char。咱們知道char類型的數據是一次性分配存儲空間的,不管之後你怎麼修改,數據始終在該存儲空間內的,不會產生碎片。而varchar則不一樣,varchar的數據長度是可變的,當修改後的數據大於當前存儲長度時,就會產生碎片,若是該應用是反覆修改數據的應用,那麼長此以往就是產生無數碎片,效率可想而知。
原則三:理解varchar的存儲空間和內存空間的區別,合理指定varchar的長度。咱們知道varchar的存儲長度是根據字符串的長度而定的,可是運行時佔用的內存空間倒是按照定義的長度分配內存空間的(個人理解,不知道是否正確)。這個現象致使存儲一個字符串,好比通訊地址,通暢在100個字符內就能存儲完成,因而varchar(100)是一個合理的選擇,可是因爲以前講的,可能有人圖方便使用varchar(500),反正用的存儲空間是同樣的,可是效果確實不同的。在內存模型中varchar(100)與varchar(500)是兩碼事,後者比前者佔用多5倍的內存空間,在臨時表和排序的時候這個差異幾乎可能差一個數量級,因而效率可想而知。
轉載註明來源:www.blogguy.cn
基本上解釋完char和varchar,這裏順帶看看Nchar和Nvarchar是什麼?
nvarchar表示可變長度 Unicode 數據,其最大長度爲 4,000 字符;nchar表示固定長度的 Unicode 數據,最大長度爲 4,000 個字符。
那Nchar和Nvarchar在什麼狀況下使用呢?咱們知道字符 中,英文字符只須要一個字節存儲就足夠了,但漢字衆多,須要兩個字節存儲,英文與漢字同時存在時容易形成混亂,Unicode字符集就是爲了解決字符集這 種不兼容的問題而產生的,它全部的字符都用兩個字節表示,即英文字符也是用兩個字節表示。因而支持多語言的站點應考慮使用 Unicode nchar 或 nvarchar 數據類型以儘可能減小字符轉換問題。一樣的解釋還有下面咱們要研討的NText。
下面咱們看看text和blob
text分爲4種類型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT,分別對應不一樣的長度。text是非二進制字符串,而且須要指定字符集,並按照該字符集進行校驗和排序。只能存儲純文本,能夠看做是VARCHAR在長度不足時的擴展。
blob也分爲4種類型:TINYBLOB,BLOB,mediumblob和LongBlob,分別對應不一樣的長度,blob存儲的是二進制數據,所以無需字符集校驗,blob除了存儲文本信息外,因爲二進制存儲格式,因此還能夠保存圖片等信息,blob能夠看做是VARBINARY在長度不足時的擴展。
text和blob的各類類型存儲長度,咱們用以下的表格表示:
TinyBlob 最大長度255個字元(2^8-1)
TinyText 最大長度255個字元(2^8-1)
Blob 最大長度65535個字元(2^16-1)
Text 最大長度65535個字元(2^16-1)
MediumBlob 最大長度 16777215 個字元(2^24-1)
MediumText 最大長度 16777215 個字元(2^24-1
LongBlob 最大長度4294967295個字元 (2^32-1)
LongText 最大長度4294967295個字元 (2^32-1)
好了,到此char,varchar,text,blob內容探討基本完成了,下面是我再次複習一下有關int型數據的內容,列在這裏方便對比。
轉載請註明來源:www.blogguy.cn