MySQL技术|MySQL的一个表最多可以有多少个字段

问题由来

引用我们客户的原话

创建如下表,提示我:

[Err] 1118 - 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 BLOBs

如果我将下面表中的varchar(200),修改成text(或blob):报错变为另一个:

Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

我们查阅了很多的资料,不确定The maximum row size到底是65535 还是8126?原理是什么?
三种报错的疑惑。

我们整理了一下,其实类似的错误有三种:

•错误1 创建表报maximum row size > 65535

[Err] 1118 - 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 BLOBs

•错误2 创建表报Row size too large (> 8126)

Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

•错误3 表创建成功但是插入报 Row size too large (> 8126)

ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

到底要闹哪样?这么多错误,还都不一样,MySQL到底要闹哪样?别急,一个问题一个问题的看。

错误1:

这个报错其实我们查询MySQL官方手册就可以查询到, 对于一行记录最大的限制是65535字节。为什么是65535,不要问我,手册也没说:)—-一行数据里面字段长度定义有64k,我也是醉了

错误2:

既生瑜何生亮?有了65535的限制以后还有一个8126的限制是为什么呢?

MySQL是分两层的,MySQL Server层 + 存储引擎层。

第2个问题其实是MySQL除了在Server层做了一次限制还会在Innodb存储引擎层在做一次限制。

innodb为了保证B+TREE是一个平衡树结构,强制要求一条记录的大小不能超过一个页大小的一半。这也就是我们上面看到的第二个错误。

下面是innodb B+树的结构,我们可以想象一下二分查找时,一个页的只有一条数据会是什么样子?

每个页只有一条数据的查找就变成了链表查找了。这样就没有二分查找的意义了。

而MySQL中默认的页大小是16K,16K的一半是8196字节减去一些元数据信息就得出了8126这个数字。

这就是8126的由来。

错误3:

突破错误2

8126是不是不能突破的呢?

我们这里就有个案例:按照附1的建表语句建立一个150个字段,每个字段是100个字符(特地使用了ASCII字符集,这样一个字符就是一个字节)的表。

150 * 100=15000 > 8126。按照上面的说法,应该要报错的,

但是各位可以在自己的数据库上试一下,表能够建立成功,这是为什么呢?

其实MySQL在计算字段长度的时候并不是按照字段的全部长度来记的。

列字段小于40个字节的都会按实际字节计算,如果大于20 * 2=40 字节就只会按40字节。

对应到MySQL代码中storage/innobase/dict/dict0dict.cc的dict_index_too_big_for_tree()中:

1.  
2.           field_max_size = dict_col_get_max_size(col);
3.  
4.           field_ext_max_size = field_max_size < 256 ? 1 : 2;
5.  
6.  
7.  
8.  
9.  
10.          if (field->prefix_len) {
11. 
12.              if (field->prefix_len < field_max_size) {
13. 
14.                  field_max_size = field->prefix_len;
15. 
16.              }
17. 
18.          } else if (field_max_size > BTR_EXTERN_FIELD_REF_SIZE * 2
19. 
20.               ¦ && dict_index_is_clust(new_index)) {
21. 
22. 
23. 
24. 
25. 
26.              /* In the worst case, we have a locally stored
27. 
28.              column of BTR_EXTERN_FIELD_REF_SIZE * 2 bytes.
29. 
30.              The length can be stored in one byte.  If the
31. 
32.              column were stored externally, the lengths in
33. 
34.              the clustered index page would be
35. 
36.              BTR_EXTERN_FIELD_REF_SIZE and 2. */
37. 
38.              field_max_size = BTR_EXTERN_FIELD_REF_SIZE * 2;
39. 
40.              field_ext_max_size = 1;
41. 
42.          }

也就是说,如果字段长度超过BTR_EXTERN_FIELD_REF_SIZE * 2,字段就只算20 * 2=40(BTR_EXTERN_FIELD_REF_SIZE=20)

举例如下:

•创建一个300个字段长度类型为varchar(30)的表,在创建时不会创建成功。因为varchar(30)没有超过202,那么总长度就是30030=9000 > 8126就会创建失败。

•创建一个150个字段长度类型为varchar(100)的表可以创建成功。因为varchar(100) 大于了202那么就只会按40计算 总长度就是15020*2=6000 < 8126 就会创建成功。

•这个20字节是不是看着有点眼熟,可以联系到InnoDB的一个参数:innodb_file_format。该参数用于设置Innodb表内部存储的文件格式,该参数可设置为Antelope,Barracuda两种格式。

•Antelope是MySQL原始的记录格式,是较古老的记录格式。

在这种格式记录下Innodb 对于大字段的处理如下:

对于大字段,innodb只会存放前DICT_ANTELOPE_MAX_INDEX_COL_LEN(768)字节在数据页中,超过768字节都会放到溢出页中。这种方式也是B+TREE结构,但是也并不是完美的,因为我们将大字段存放到了数据页中会造成叶子节点的个数会很多,同样会造成非叶子节点的的个数增加。最终导致索引层级增高,访问IO次数增加。

•Barracuda格式是InnoDB新的存储格式

他的存储方式如下:

在Barracuda格式下,会用20字节的指针指向溢出页,这样做的好处就是不会造成索引层级的增高。

回到错误3

回归正题,第二个错误我们可以越过去,但是我们是不是能够真的插入150个100字符的字段列。
用附2的插入语句试一下就知道,错误3也会报错出来。

也就是说表可以创建成功但是插入却失败,原因如下:

•Antelope格式下的COMPACT大字段按照DICT_ANTELOPE_MAX_INDEX_COL_LEN(768)字节溢出页。varchar(100)没有存储为溢出页。

•Barracuda的DYNAMIC和COMPRESSED格式下只有长字段才会用20字节溢出页的方式,varchar(100)也没有存储为溢出页。

引用reference的原文如下:

When a table is created with ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED, long variable-length column values (for VARBINARY,VARCHAR, BLOB, and TEXT columns) are stored fully off-page, and the clustered index record contains only a 20-byte pointer to the overflow page. InnoDB will also store long CHAR column values off-page if the column value is greater than or equal to 768 bytes, which can occur when the maximum byte length of the character set is greater than 3, as it is with utf8mb4, for example.

Whether any columns are stored off-page depends on the page size and the total size of the row. When the row is too long, InnoDBchooses the longest columns for off-page storage until the clustered index record fits on the B-tree page. TEXT and BLOB columns that are less than or equal to 40 bytes are always stored in-line.

总结

总的来说,

•MySQL Server最多只允许4096个字段

•InnoDB 最多只能有1000个字段

•字段长度加起来如果超过65535,MySQL server层就会拒绝创建表

•字段长度加起来(根据溢出页指针来计算字段长度,大于40的,溢出,只算40个字节)如果超过8126,InnoDB拒绝创建表

•表结构中根据ROW_FORMAT的存储格式确定行内部保留的字节数(20 VS 768),最终确定一行数据是否小于8126,如果大于8126,报错。

建议

1.放弃使用Antelope这种古老的存储格式吧,原因上面也说到了把大字段的前768字节放在数据页中,这样会导致索引的层级很高,会直接影响到查询的性能。

2.对于大字段类型建议单独存放到一张表中,不要与经常访问的表放在一起,会造成物理IO的增加。

参考

MySQL reference: Limits on Table Column Count and Row Size

MySQL reference: innodb row format dynamic

mysqlserverteam:Externally Stored Fields in InnoDB

MySQL · 引擎特性 · InnoDB 文件系统之文件物理结构

附1. 建表语句

附上测试的建表语句和insert语句,有兴趣的朋友可以自己按照上面的几种方式在Antelope和Barracuda的几种不同ROW_FORMAT格式上试试。

1.  
2.  create table xjblg1
3.  
4.  (
5.  
6.    jydm                         VARCHAR(100),
7.  
8.    rq                           VARCHAR(100),
9.  
10.   cb                           VARCHAR(100),
11. 
12.   khdkjdkjjse                  VARCHAR(100),
13. 
14.   xyhjkjzje                    VARCHAR(100),
15. 
16.   khckhtycfkxjzje              VARCHAR(100),
17. 
18.   qzkhck                       VARCHAR(100),
19. 
20.   tyjqtjrjgcfk                 VARCHAR(100),
21. 
22.   shcftyjqtjrjgje              VARCHAR(100),
23. 
24.   crzjxjlr                     VARCHAR(100),
25. 
26.   shdcczjje                    VARCHAR(100),
27. 
28.   xsdmchgssddxj                VARCHAR(100),
29. 
30.   shdmrfsxje                   VARCHAR(100),
31. 
32.   czjyxjrzcjzje                VARCHAR(100),
33. 
34.   sqlxsxfjyjdxj                VARCHAR(100),
35. 
36.   sdlx                         VARCHAR(100),
37. 
38.   sddsxf                       VARCHAR(100),
39. 
40.   jrqywlsrsddxj                VARCHAR(100),
41. 
42.   zjywsrsddxj                  VARCHAR(100),
43. 
44.   zqtzsysddxj                  VARCHAR(100),
45. 
46.   hdjsysddxj                   VARCHAR(100),
47. 
48.   qtyyjyywjsrsddxj             VARCHAR(100),
49. 
50.   crbzjsddxj                   VARCHAR(100),
51. 
52.   sddwtzj                      VARCHAR(100),
53. 
54.   gjsxjlr                      VARCHAR(100),
55. 
56.   txsddxj                      VARCHAR(100),
57. 
58.   xssptglwsddxj                VARCHAR(100),
59. 
60.   sddsffh                      VARCHAR(100),
61. 
62.   qtfzzjlrdxj                  VARCHAR(100),
63. 
64.   shdyyyqndhxddkjyskx          VARCHAR(100),
65. 
66.   qtyfzskjslcdxj               VARCHAR(100),
67. 
68.   czdzzcsddxj                  VARCHAR(100),
69. 
70.   sdqtyjyhdygdxj               VARCHAR(100),
71. 
72.   jyhdxjlrxj                   VARCHAR(100),
73. 
74.   khdkjdkjzje                  VARCHAR(100),
75. 
76.   cfzyyhhtykxjzje              VARCHAR(100),
77. 
78.   cfzyyh                       VARCHAR(100),
79. 
80.   cftyjqtjgck                  VARCHAR(100),
81. 
82.   cczjjxjlc                    VARCHAR(100),
83. 
84.   chzyyhjkxzyyhjkjjse          VARCHAR(100),
85. 
86.   zfdck                        VARCHAR(100),
87. 
88.   jstyjqtjrjgcfje              VARCHAR(100),
89. 
90.   chtyjqtjrjgcrje              VARCHAR(100),
91. 
92.   chmchgkxje                   VARCHAR(100),
93. 
94.   zfmrfskxje                   VARCHAR(100),
95. 
96.   czkgcsjrzcjjse               VARCHAR(100),
97. 
98.   zflxsxfjyjdxj                VARCHAR(100),
99. 
100.      zfdlx                        VARCHAR(100),
101.    
102.      sxfzczfdxj                   VARCHAR(100),
103.    
104.      zfgzgyjwzgzfdxj              VARCHAR(100),
105.    
106.      zfdgxsf                      VARCHAR(100),
107.    
108.      yxjzfdyyfy                   VARCHAR(100),
109.    
110.      yjrjgwlzcdxjje               VARCHAR(100),
111.    
112.      txzfdxj                      VARCHAR(100),
113.    
114.      yhxdzdkjlxsh                 VARCHAR(100),
115.    
116.      gjsxjlc                      VARCHAR(100),
117.    
118.      gmspjslwzfdxj                VARCHAR(100),
119.    
120.      jrqtzjjjse                   VARCHAR(100),
121.    
122.      qtzcjszcdxj                  VARCHAR(100),
123.    
124.      qtyszfkjsshdxj               VARCHAR(100),
125.    
126.      zfqtyjyhdygdxj               VARCHAR(100),
127.    
128.      jyhdxjlcxj                   VARCHAR(100),
129.    
130.      jyhdcsdxjllje                VARCHAR(100),
131.    
132.      shtzsddxj                    VARCHAR(100),
133.    
134.      qdtzsysddxj                  VARCHAR(100),
135.    
136.      qzfdglhlrssddxj              VARCHAR(100),
137.    
138.      czgdzcwxzcjqtzcesddxj        VARCHAR(100),
139.    
140.      czgqtzssddxj                 VARCHAR(100),
141.    
142.      qdzgsjqtyydwssddxjje         VARCHAR(100),
143.    
144.      sdqtytzhdygdxj               VARCHAR(100),
145.    
146.      tzhdxjlrxj                   VARCHAR(100),
147.    
148.      tzzfdxj                      VARCHAR(100),
149.    
150.      qyxtzzzzfdxj                 VARCHAR(100),
151.    
152.      zqtzszfdxj                   VARCHAR(100),
153.    
154.      gmzgslyqyjhyqytzszfdxjje     VARCHAR(100),
155.    
156.      zjzjgcszfdxj                 VARCHAR(100),
157.    
158.      gjgdzcwxzchqtcqzczfdxj       VARCHAR(100),
159.    
160.      qdzgsjqtyydwzfdxjje          VARCHAR(100),
161.    
162.      zfdqtytzhdygdxj              VARCHAR(100),
163.    
164.      tzhdxjlcxj                   VARCHAR(100),
165.    
166.      tzhdcsdxjllje                VARCHAR(100),
167.    
168.      xstzssddxj                   VARCHAR(100),
169.    
170.      fxzqhzcsxsdxj                VARCHAR(100),
171.    
172.      qdjksddxj                    VARCHAR(100),
173.    
174.      fxzqsddxj                    VARCHAR(100),
175.    
176.      qzfxcjzqsddxj                VARCHAR(100),
177.    
178.      zjgbssddxj                   VARCHAR(100),
179.    
180.      sdqtyczhdygdxj               VARCHAR(100),
181.    
182.      czhdxjlrxj                   VARCHAR(100),
183.    
184.      chzwszfdxj                   VARCHAR(100),
185.    
186.      fpgllrhcflxzfdxj             VARCHAR(100),
187.    
188.      qzcflxszfdxj                 VARCHAR(100),
189.    
190.      zfxgfxfy                     VARCHAR(100),
191.    
192.      zfqtyczhdygdxj               VARCHAR(100),
193.    
194.      czhdxjlcxj                   VARCHAR(100),
195.    
196.      czhdcsdxjllje                VARCHAR(100),
197.    
198.      hlbddxjjxjdjwdyx             VARCHAR(100),
199.    
200.      xjjxjdjwjzje                 VARCHAR(100),
201.    
202.      qcxjjxjdjwye                 VARCHAR(100),
203.    
204.      qmxjjxjdjwye                 VARCHAR(100),
205.    
206.      jlr                          VARCHAR(100),
207.    
208.      ssgdqy                       VARCHAR(100),
209.    
210.      qzjtdhzzb                    VARCHAR(100),
211.    
212.      jtddksszb                    VARCHAR(100),
213.    
214.      jtdzcjzzb                    VARCHAR(100),
215.    
216.      chcftyjzzb                   VARCHAR(100),
217.    
218.      jtdzzcjzzb                   VARCHAR(100),
219.    
220.      jtqtzcjzzb                   VARCHAR(100),
221.    
222.      gdzczjyqzcchscxswzccj        VARCHAR(100),
223.    
224.      tzxfdczj                     VARCHAR(100),
225.    
226.      wxzcdyzcjqtzcdtx             VARCHAR(100),
227.    
228.      qzwxzctx                     VARCHAR(100),
229.    
230.      cqdtfytx                     VARCHAR(100),
231.    
232.      czgdzcwxzchqtcqzcdsssy       VARCHAR(100),
233.    
234.      cztzxfdcdsssy                VARCHAR(100),
235.    
236.      gdzcbfss                     VARCHAR(100),
237.    
238.      cwfy                         VARCHAR(100),
239.    
240.      dtfydjszj                    VARCHAR(100),
241.    
242.      ytfydzjjs                    VARCHAR(100),
243.    
244.      tzssjsy                      VARCHAR(100),
245.    
246.      gyjzbdsyss                   VARCHAR(100),
247.    
248.      hdsy                         VARCHAR(100),
249.    
250.      ysjrgjjyjsy                  VARCHAR(100),
251.    
252.      chdjs                        VARCHAR(100),
253.    
254.      dkdjs                        VARCHAR(100),
255.    
256.      ckdzj                        VARCHAR(100),
257.    
258.      cjkxdjz                      VARCHAR(100),
259.    
260.      yjfzdzj                      VARCHAR(100),
261.    
262.      sdyhxkx                      VARCHAR(100),
263.    
264.      jrfzdzj                      VARCHAR(100),
265.    
266.      dysdszcdjs                   VARCHAR(100),
267.    
268.      dysdsfzdzj                   VARCHAR(100),
269.    
270.      jyxysxmdjs                   VARCHAR(100),
271.    
272.      jyxyfxmdzj                   VARCHAR(100),
273.    
274.      jyxqtzcdjs                   VARCHAR(100),
275.    
276.      jyxqtfzdzj                   VARCHAR(100),
277.    
278.      qt                           VARCHAR(100),
279.    
280.      jyhdxjllje                   VARCHAR(100),
281.    
282.      ygdzcchzw                    VARCHAR(100),
283.    
284.      ytzchzw                      VARCHAR(100),
285.    
286.      ygdzcjxtz                    VARCHAR(100),
287.    
288.      zyzwzb                       VARCHAR(100),
289.    
290.      ynndqdkzhgszq                VARCHAR(100),
291.    
292.      rzzrgdzc                     VARCHAR(100),
293.    
294.      qtbsjxjszdtzhczhdje          VARCHAR(100),
295.    
296.      xjdqmye                      VARCHAR(100),
297.    
298.      jxjdqcye                     VARCHAR(100),
299.    
300.      xjdjwdqmye                   VARCHAR(100),
301.    
302.      jxjdjwdqcye                  VARCHAR(100),
303.    
304.      xjjxjdjwjzje1                VARCHAR(100)
305.    
306.    ) ENGINE=InnoDB DEFAULT CHARSET=ascii;;
307.    
308.    

附2. insert 语句

1.  
2.  insert into xjblg1 values( 
3.  
4.  repeat('y',100),
5.  
6.  repeat('y',100),
7.  
8.  repeat('y',100),
9.  
10. repeat('y',100),
11. 
12. repeat('y',100),
13. 
14. repeat('y',100),
15. 
16. repeat('y',100),
17. 
18. repeat('y',100),
19. 
20. repeat('y',100),
21. 
22. repeat('y',100),
23. 
24. repeat('y',100),
25. 
26. repeat('y',100),
27. 
28. repeat('y',100),
29. 
30. repeat('y',100),
31. 
32. repeat('y',100),
33. 
34. repeat('y',100),
35. 
36. repeat('y',100),
37. 
38. repeat('y',100),
39. 
40. repeat('y',100),
41. 
42. repeat('y',100),
43. 
44. repeat('y',100),
45. 
46. repeat('y',100),
47. 
48. repeat('y',100),
49. 
50. repeat('y',100),
51. 
52. repeat('y',100),
53. 
54. repeat('y',100),
55. 
56. repeat('y',100),
57. 
58. repeat('y',100),
59. 
60. repeat('y',100),
61. 
62. repeat('y',100),
63. 
64. repeat('y',100),
65. 
66. repeat('y',100),
67. 
68. repeat('y',100),
69. 
70. repeat('y',100),
71. 
72. repeat('y',100),
73. 
74. repeat('y',100),
75. 
76. repeat('y',100),
77. 
78. repeat('y',100),
79. 
80. repeat('y',100),
81. 
82. repeat('y',100),
83. 
84. repeat('y',100),
85. 
86. repeat('y',100),
87. 
88. repeat('y',100),
89. 
90. repeat('y',100),
91. 
92. repeat('y',100),
93. 
94. repeat('y',100),
95. 
96. repeat('y',100),
97. 
98. repeat('y',100),
99. 
100.    repeat('y',100),
101.    
102.    repeat('y',100),
103.    
104.    repeat('y',100),
105.    
106.    repeat('y',100),
107.    
108.    repeat('y',100),
109.    
110.    repeat('y',100),
111.    
112.    repeat('y',100),
113.    
114.    repeat('y',100),
115.    
116.    repeat('y',100),
117.    
118.    repeat('y',100),
119.    
120.    repeat('y',100),
121.    
122.    repeat('y',100),
123.    
124.    repeat('y',100),
125.    
126.    repeat('y',100),
127.    
128.    repeat('y',100),
129.    
130.    repeat('y',100),
131.    
132.    repeat('y',100),
133.    
134.    repeat('y',100),
135.    
136.    repeat('y',100),
137.    
138.    repeat('y',100),
139.    
140.    repeat('y',100),
141.    
142.    repeat('y',100),
143.    
144.    repeat('y',100),
145.    
146.    repeat('y',100),
147.    
148.    repeat('y',100),
149.    
150.    repeat('y',100),
151.    
152.    repeat('y',100),
153.    
154.    repeat('y',100),
155.    
156.    repeat('y',100),
157.    
158.    repeat('y',100),
159.    
160.    repeat('y',100),
161.    
162.    repeat('y',100),
163.    
164.    repeat('y',100),
165.    
166.    repeat('y',100),
167.    
168.    repeat('y',100),
169.    
170.    repeat('y',100),
171.    
172.    repeat('y',100),
173.    
174.    repeat('y',100),
175.    
176.    repeat('y',100),
177.    
178.    repeat('y',100),
179.    
180.    repeat('y',100),
181.    
182.    repeat('y',100),
183.    
184.    repeat('y',100),
185.    
186.    repeat('y',100),
187.    
188.    repeat('y',100),
189.    
190.    repeat('y',100),
191.    
192.    repeat('y',100),
193.    
194.    repeat('y',100),
195.    
196.    repeat('y',100),
197.    
198.    repeat('y',100),
199.    
200.    repeat('y',100),
201.    
202.    repeat('y',100),
203.    
204.    repeat('y',100),
205.    
206.    repeat('y',100),
207.    
208.    repeat('y',100),
209.    
210.    repeat('y',100),
211.    
212.    repeat('y',100),
213.    
214.    repeat('y',100),
215.    
216.    repeat('y',100),
217.    
218.    repeat('y',100),
219.    
220.    repeat('y',100),
221.    
222.    repeat('y',100),
223.    
224.    repeat('y',100),
225.    
226.    repeat('y',100),
227.    
228.    repeat('y',100),
229.    
230.    repeat('y',100),
231.    
232.    repeat('y',100),
233.    
234.    repeat('y',100),
235.    
236.    repeat('y',100),
237.    
238.    repeat('y',100),
239.    
240.    repeat('y',100),
241.    
242.    repeat('y',100),
243.    
244.    repeat('y',100),
245.    
246.    repeat('y',100),
247.    
248.    repeat('y',100),
249.    
250.    repeat('y',100),
251.    
252.    repeat('y',100),
253.    
254.    repeat('y',100),
255.    
256.    repeat('y',100),
257.    
258.    repeat('y',100),
259.    
260.    repeat('y',100),
261.    
262.    repeat('y',100),
263.    
264.    repeat('y',100),
265.    
266.    repeat('y',100),
267.    
268.    repeat('y',100),
269.    
270.    repeat('y',100),
271.    
272.    repeat('y',100),
273.    
274.    repeat('y',100),
275.    
276.    repeat('y',100),
277.    
278.    repeat('y',100),
279.    
280.    repeat('y',100),
281.    
282.    repeat('y',100),
283.    
284.    repeat('y',100),
285.    
286.    repeat('y',100),
287.    
288.    repeat('y',100),
289.    
290.    repeat('y',100),
291.    
292.    repeat('y',100),
293.    
294.    repeat('y',100),
295.    
296.    repeat('y',100),
297.    
298.    repeat('y',100),
299.    
300.    repeat('y',100),
301.    
302.    repeat('y',100));

发表评论

电子邮件地址不会被公开。 必填项已用*标注