MySQL的一個表最多可以有多少個欄位
原文:http://mp.weixin.qq.com/s?__biz=MzAwMjkyMjEwNg==&mid=2247483785&idx=1&sn=1d90a44915d1028c6dc150367e1af033#rd
問題由來引用我們客戶的原話:
*建立如下表,提示我:*
*如果我將下面表中的varchar(200),修改成text(或blob):報錯變為另一個:*
*我們查閱了很多的資料,不確定The maximum row size到底是65535 還是8126?原理是什麼?*
●
● 錯誤2 建立表報Row size too large (> 8126)
● 錯誤3 表建立成功但是插入報 Row size too large (> 8126)
別急,一個問題一個問題的看。
錯誤1這個報錯其實我們查詢MySQL官方手冊就可以查詢到, 對於一行記錄最大的限制是65535位元組。為什麼是65535,不要問我,手冊也沒說:)——一行資料裡面欄位長度定義有64k,我也是醉了。錯誤2既生瑜何生亮?有了65535的限制以後還有一個8126的限制是為什麼呢?
MySQL是分兩層的,MySQL Server層 + 儲存引擎層。
第2個問題其實是MySQL除了在Server層做了一次限制還會在Innodb儲存引擎層在做一次限制。
innodb為了保證B+TREE是一個平衡樹結構,強制要求一條記錄的大小不能超過一個頁大小的一半。這也就是我們上面看到的第二個錯誤。
下面是innodb B+樹的結構,我們可以想象一下二分查詢時,一個頁的只有一條資料會是什麼樣子?
每個頁只有一條資料的查詢就變成了連結串列查找了。這樣就沒有二分查詢的意義了。
8126是不是不能突破的呢?
我們這裡就有個案例:按照附1的建表語句建立一個150個欄位,每個欄位是100個字元(特地使用了ASCII字符集,這樣一個字元就是一個位元組)的表。(建表語句和insert語句參見附錄)
150 * 100=15000 > 8126。按照上面的說法,應該要報錯的,但是各位可以在自己的資料庫上試一下,表能夠建立成功,這是為什麼呢?其實MySQL在計算欄位長度的時候並不是按照欄位的全部長度來記的。列欄位小於40個位元組的都會按實際位元組計算,如果大於20 * 2=40 位元組就只會按40位元組。對應到MySQL程式碼中storage/innobase/dict/dict0dict.cc的dict_index_too_big_for_tree()中:
也就是說,如果欄位長度超過BTR_EXTERN_FIELD_REF_SIZE * 2,欄位就只算20 * 2=40(BTR_EXTERN_FIELD_REF_SIZE=20)
在這種格式記錄下Innodb 對於大欄位的處理如下:
對於大欄位,innodb只會存放前DICT_ANTELOPE_MAX_INDEX_COL_LEN(768)位元組在資料頁中,超過768位元組都會放到溢位頁中。這種方式也是B+TREE結構,但是也並不是完美的,因為我們將大欄位存放到了資料頁中會造成葉子節點的個數會很多,同樣會造成非葉子節點的的個數增加。最終導致索引層級增高,訪問IO次數增加。
他的溢位儲存方式如下:
在Barracuda格式下,會用20位元組的指標指向溢位頁,這樣做的好處就是不會造成索引層級的增高。
引用reference的原文如下:
附上測試的建表語句和insert語句,有興趣的朋友可以自己按照上面的幾種方式在Antelope和Barracuda的幾種不同ROW_FORMAT格式上試試。
相關推薦
MySQL的一個表最多可以有多少個欄位
原文:http://mp.weixin.qq.com/s?__biz=MzAwMjkyMjEwNg==&mid=2247483785&idx=1&sn=1d90a44915d1028c6dc150367e1af033#rd 問題由來引用我們客戶的原話
sql 兩張表對比多出的欄位值
比如表dbo.DangAn表中有的而dbo.YongHu表沒有的值都顯示出來 SELECT * FROM dbo.DangAn a WHERE a.xCode NOT IN( SELECT b.yCode FROM dbo.YongHu b) 表dbo.YongHu有的欄位
一張表中把兩個欄位相同的資料合併(listagg函式)
問題描述: 如下圖所示,需求是把省和產品相同的NTID合併到一起。 元資料: 想要的結果: 折騰了半天,結果經專案組大神指教,說有一個函式可以直接完成上訴操作。 listagg(); 程式碼如下: select yearmonth, listagg(ntid,
Linux下統計出現次數最多的指定欄位值
假設桌面上有一個data.txt文字,內容如下: {id='xxx' info='xxx' kk='xxx' target='111111' dd='xxx'} {id='xxx' info='xxx' kk='xxx' target='777' dd='xxx'} {i
oracle資料庫表中某幾個欄位的重複資料去重
delete from szpj_biz_水文觀測資料 a where (a.觀測點_id, a.觀測時間, a.取樣位置) in (select 觀測點_id, 觀測時間, 取樣位置 from szpj_biz_水文觀測資料 g
mysql建立表的時候,新增欄位註釋
mysql建立表的時候,新增欄位註釋 直接po程式碼和案例 #建立表的時候寫註釋 CREATE TABLE userinfo( id INT COMMENT '編號', uname VARCHAR(40) COMMENT '使用者名稱', address VARCHAR(120)
mysql SQL語句order by兩個欄位同時排序
ORDER BY 後可加2個欄位,用英文逗號隔開。 f1用升序, f2降序,sql該這樣寫 ORDER BY f1, f2 DESC 也可以這樣寫,更清楚: ORDER BY f1
將一個表的資料的某些欄位更新到另一個表裡面的某些欄位
update jwxt.jy_pyjhyq a set( a.PYJHZWMC ,a.ywpymbzw,a.ywpymbyw,a.ywpyyqzw,a.ywpyyqyw,a.zgxkzw,a.zgxkyw,a.jhxzzw,a.jhxzyw,a.pyjhyqzw,a.py
資料庫中查詢2張表中某兩個欄位不同的資料
例: 表a 欄位 as aid at ao 表b 欄位 bs bid bf bg bh 其中表a中欄位as 的資料是 1 5 7 2 9 90 87 23 其中表b中欄位bs 的資料是
MySQL根據某一個或者多個欄位查詢重複資料,並且保留某欄位值最大的記錄
問題場景 當系統沒有處理好併發操作的情況下,操作人員同時操作一張表的情況下,資料庫有可能被插入相同記錄,這些會帶來隱藏的bug。 解決思路一 解決併發操作的衝突。 解決思路二 對資料庫(MySQL)某張表去重,首先確定你的業務是否允許重複,不允許你
mysql一張表多個欄位關聯另一張表查詢
如下:一張訂單表多個欄位關聯使用者表: 1.連結串列查詢 SELECT cu.id AS 'id',cu.version AS 'version',cu.cid AS 'cid',cu.uid AS 'uid',cu.shopName AS 'shopName',cu.address AS 'addre
mysql建立表多個欄位的唯一約束
mysql中有些表有時需要做一些欄位的唯一約束,當然你也可以在insert前判斷有無的方式來防止重複,如果不想額外增加程式碼來更靈活的實現一些欄位的唯一約束,mysql提供了兩種方式: 1.unique key alter table xx add unique ke
給定一個二維平面,平面上有 n 個點,求最多有多少個點在同一條直線上。
需求:給定一個二維平面,平面上有 n 個點,求最多有多少個點在同一條直線上。 分析思路: 1、將所有點二維座標化,即定義出所有點的x,y座標值 2、遍歷出所有取出兩點的情況(不考慮先後順序),根據任意兩點都確定一條直線,直線引數為k斜率,b與y軸交點的縱座標(此時x=0),將他們放入一個
oracle 中 一張表最多能夠建立多少個欄位?
oracle 中 一張表最多能夠建立多少個欄位? 收藏帖子 回覆 比比路克 結帖率 100% help! 問題點數:20分 0 2002-01-25 15:51:39 回覆數 4 只看樓主 引
【mysql】sql刪除多個欄位重複資料有主鍵和沒主鍵解決方法
table user name age nub 張三 12 23 張三 12 23 張三 12 23 李四 13 21 李四 13 21 王五 11 25
mysql 刪除單表內多個欄位重複的資料
遇到個問題,一個表內兩個欄位應該加上unique約束,但沒加導致出現重複資料,網上找到一條sql可以刪掉重複資料,原sql是這樣的: DELETE from test WHERE (mid,uid) in (SELECT mid,uid FROM test GROUP
Hibernate中多對多的annotation的寫法(中間表可以有多個欄位)
一般情況下,多對多的關聯關係是需要中間表的; 情況一:如果中間表僅僅是做關聯用的,它裡面僅有2個外來鍵做聯合主鍵,則使用ManyToMany(不用寫中間表的Model,只需要寫出兩張主表的model即可) 學生表 @Entity@Table(name = "T_STUDENT")@SequenceGener
oracle 用一個表的多個欄位更新另一個表對應的多個欄位
update wx_weather a set (a.high_l,a.low_l)= (select high_l, low_l from wx_original_weather b where a
發現mysql一個表可以有幾個唯一索引
mysql一個表可以有多個唯一索引。如果能確定某個資料列將只包含彼此各不相同的值,在為這個資料列建立索引的時候就應該用關鍵字UNIQUE把它定義為一個唯一索引。這麼做的好處:一是簡化了MySQL對這個索引的管理工作,這個索引也因此而變得更有效率。二是MySQL會在有新記錄插入