MySql中varchar長度的設置問題

根據自己多年的工作經驗,特別是在接收舊的項目時,varcahr的長度設置有不同的風格,針對varchar長度的設置問題,自己劃分了不同的門派。

1.強迫癥派:長度設置為4或者8的倍數,達到內存對齊的目的;

2.貼心派:長度設置成(2^n)-1;

3.務實派:需要多長就設置多長,不關心2的幾次冪;

4.逍遙派:varchar是存儲可變長字符串的,n值盡可能設置的大,比如varchar(1000)。

下面分析那種方案更合理:

1.varchar(n)的最大值字符數是多少

varchar的最大可以保存65535字節,但是具體保存多少個字符,不同的編碼不一樣。

MySql 5.0 之前的版本: n指的是n個字節
n的最大值是65535,如果存放utf-8格式只能保存 (n / 3)個漢字,即如果varchar(20) 那么只能保存6個漢字;

MySql 5.0 之后的版本: n指的是n個字符
如果存放utf-8格式,那么無論是數字,字母還是漢字,都可存放n個,即如果varchar(20) 那么可以保存20個漢字(自己親測可以);
gbk類型:varchar(n)中每個字符最多占2個字節,最大長度不能超過(65535 / 2);
utf-8類型:varchar(n)中每個字符最多占3個字節,最大長度不能超過(65535 / 3)。

2.varchar(n)需要1到2個額外字節記錄長度n的值

當n<=255的時候,只需要1個字節記錄即可(數據表示范圍:0 ~ (2^8-1),即0~255);當n>255的時候,則需要2個字節存儲n的值((2^8)~ (2^16)-1,即256~65535)。

varchar字段報錯的實際值得長度保存在第一個或者前兩個字節中。
所以:
a.如果varchar(20),實際是需要1+20個字節的存儲空間;
b.如果varchar(255),實際是需要1+255個字節的存儲空間;
c.如果varchar(256),實際是需要2+256個字節的存儲空間;
d.如果varchar(500),實際是需要2+500個字節的存儲空間.

因此1.強迫癥派的n=4或者8的倍數達到內存對齊的目的是不成立的,如果要達到內存對齊,varchar長度應該為(2^n)-1才能夠達到,所以強迫癥派的方法不可取。

3.varchar的內存對齊的問題

因為varchar是存儲可變長字符串,
因此:
a.如果name varchar(8),那么name='12345678',實際長度為1+8;
b.如果name varchar(32),那么name='12345678',實際長度為1+8;
c.如果name varchar(16),那么name='1234',實際長度為1+4;

估:
貼心派的varchar長度應該為(2^n)-1是不能夠達到內存對齊的目的的,長度是以實際保存的字符串長度為準的,因此貼心派也是不準確的。
另外,InnoDB是以頁(page)為基本的存儲單位,一個頁會有一行或者多行(row)數據,數據的讀取是基于page的,不是按照row讀取的,因此也就沒有內存對齊的問題了。

4.n值盡可能設置的大的問題

逍遙派的結論一看就不靠譜,但是還是需要理論進行駁斥的。
在MySql在查詢是需要創建臨時表的時候(union,order by、group by,子查詢),在MySql讀取數據之前,是只知道varchar的長度n,不知道實際數據的長度的,但是讀取數據之前需要預分配內存空間,MySql是根據varchar(n)中的n來進行分配內存的,這樣也是最合理的方式,不可能分配小于n個字符的空間,因此針對逍遙派的varchar(1000)設置就會預先分配1000個字符空間,很顯然這個是十分不靠譜的設計。

結論:

varchar需要多長就設置多長,不必考慮2的多少次冪的問題。但是如果遇到了varchar(256)這種情況,你為啥不將他設置為varchar(255)呢,明顯節省了一個存儲長度的字節呀。因此務實派方案雖然最靠譜,但是也是要考慮255這個界限的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。