MySQL如何存储长度很长的数据字段

MySQL 如何存储长度很长的数据字段
最近,在⼯作中遇到了MySQL 中如何存储长度较长的字段类型问题,于是花了⼀周多的时间抽空学习了⼀下,并且记录下来。MySQL ⼤致的逻辑存储结构在这篇⽂章中有介绍,做为基本概念:InnoDB 逻辑存储结构
注:⽂中所指的⼤数据指的是长度较长的数据字段,包括varchar/varbinay/text/blob 。
Compact ⾏格式
我们⾸先来看⼀下⾏格式为Compact
是如何存储⼤数据的:
1              2              3              4              5              6              7              8              9              10              11              12              13              14              15              16              17              18              19              20              21      mysql> select version();
+-----------+
| version() |
+-----------+
| 5.1.73    |
+-----------+
1 row in
set (0.01 sec)
mysql> show table status like
'row'
aaaaaaaaaaaaaaaaaa\G;
*************************** 1. row ***************************
Name: row
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 1
Avg_row_length: 81920
Data_length: 81920
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2017-01-04 21:46:02
Update_time: NULL
Check_time: NULL
我们建⽴⼀张测试表,插⼊数据:
我们使⽤py_innodb_page_info.py
⼯具来查看表中的页分布:
可以看出,第4页的, page level 格式为数据页,存放着MySQL 的⾏数据。可以理解为MySQL 存放⼤数据的地⽅,暂且叫作外部存储页。Compact 格式没有将⼤数据全部放在数据页中,⽽是将⼀部分数据放在了外部存储页中。那么,是全部数据在外部存储页中,还是⼀部分数据。假如是⼀部分数据,这⼀部分是多少呢?
我们使⽤hexdump -Cv row.ibd 查看⼀下数据页, page level ,也就是第4
页:
1              2              3              4              5              6              7              8              9              10              11              12              13              14              15              16              17              18              19              20
21
22
23
24
25
3073 0000c000  8c 25 17 57 00 00 00 03  ff ff ff ff ff ff ff ff  |.%.W....|
3074 0000c010  00 00 00 00 00 07 3a b8  45 bf 00 00 00 00 00 00  |......:?E?......|
3075 0000c020  00 00 00 00 00 02 00 02  03 a6 80 03 00 00 00 00  |.........?......|
3076 0000c030  00 7f 00 05 00 00 00 01  00 00 00 00 00 00 00 00  |................|
3077 0000c040  00 00 00 00 00 00 00 00  00 13 00 00 00 02 00 00  |................|
3078 0000c050  00 02 00 f2 00 00 00 02  00 00 00 02 00 32 01 00  |...?.........2..|
3079 0000c060  02 00 1c 69 6e 66 69 6d  75 6d 00 02 00 0b 00 00  |...
3080 0000c070  73 75 70 72 65 6d 75 6d  14 c3 00 00 10 ff f1 00  |supremum.?...??.|
3081 0000c080  00 00 00 04 03 00 00 00  00 13 12 80 00 00 00 2d  |...............-|
3082 0000c090  01 10 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |..aaaaaaaaaaaaaa|
3083 0000c0a0  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
3084 0000c0b0  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
3085 0000c0c0  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
....
....
3128 0000c370  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
3129 0000c380  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
3130 0000c390  61 61 00 00 00 02 00 00  00 04 00 00 00 26 00 00  |aa...........&..|
3131 0000c3a0  00 00 00 00 fc fc 00 00  00 00 00 00 00 00 00 00  |....??..........|
3132 0000c3b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
3133 0000c3c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
3134 0000c3d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
...
...
4093 0000ffc0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
4094 0000ffd0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
4095 0000ffe0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
4096 0000fff0  00 00 00 00 00 70 00 63  01 a1 6c 2b 00 07 3a b8  |.....p.c.?l+..:?|
我们可以看出,数据页中存储了⼀部分数据,算下来⼀共是768字节,然后剩余部分存储在外部存储页中。那么数据页与外部存储页、外部存储页与外部存储页是如何连接在⼀起的呢?
我们观察这⼀⾏:
1)00 00 00 02:4字节,代表外部存储页所在的space id
2)00 00 00 04:4字节,代表第⼀个外部页的Page no
3)00 00 00 26:4字节,值为38,指向blob页的header
4)00 00 00 00 00 00 fc fc:8字节,代表该列存在外部存储页的总长度。此处的值为64764,加上前缀768正好是65532。(注意⼀点,虽
然表⽰BLOB长度的是8字节,实际只有4个字节能使⽤,所有对于BLOB字段,存储数据的最⼤长度为4GB。)
验证下第⼀个外部存储页的头部信息:
前38个字节为File Header(关于InnoDB数据页的详细结构请参见《MySQL技术内幕 InnoDB存储引擎》4.4),这个简单提⼀下:
1)cd c3 b6 8e:4字节,该页的checksum。
2)00 00 00 04:4字节,页偏移,此页为表空间中的第5个页。
3)00 00 00 00:4字节,当前页的上⼀个页。此页为,所以没有上⼀页。
4)00 00 00 00:4字节,当前页的下⼀个页。此页为,所以没有下⼀页。
5)00 00 00 00 00 06 b8 a2:8字节,该页最后被修改的⽇志序列位置LSN。
6)00 0a:2字节,页类型,0x000A代表BLOB页。
7)00 00 00 00 00 00 00 00:8字节,略过。
8)00 00 00 02:页属于哪个表空间,此处指表空间的ID为2。
之后是4字节的00 00 3f ca,这⾥的值为16330,代表此BLOB页的有效数据的字节数。00 00 00 05代表下⼀个BLOB页的page number。我们看最后⼀个,第8个页:
最后⼀页的有效数据⼤⼩为0x00003d9e=15774,768+16330*3+15774 = 65532字节,符合初始插⼊数据的⼤⼩。
由于这是最后⼀个,所以指向下⼀个的指针为ff ff ff ff。
由此我们可以很清晰的看出数据页与BLOB页的连接关系(引⽤淘宝数据库⽉报上的⼀张图):
我们来再看⼀个⽐较有意思的例⼦。

本文发布于:2024-09-21 05:35:39,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/361038.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   字节   值为   空间   部分   代表   长度   内幕
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议