本文引用的是2014年2月3日的innodb_ruby 0.8.8版本。
在《学习InnoDB:核心之旅》中,我在innodb_ruby项目中引入了一个新的库和命令行工具。稍后,在对innodb_ruby的介绍中,我将介绍innodb_space命令行工具的安装和一些快速演示。
在我的上一篇文章《InnoDB空间文件中的页面管理》中,我描述了InnoDB的区段、文件段和空闲空间管理结构。现在,我将提供几个使用innodb_space在实际表中检查这些结构的演示。
一个最小的空表
我创建了一个空表(模式无关紧要)来说明InnoDB页面管理结构的“最小”状态。space-page-type-regions模式将汇总同一页面类型的所有相邻区域的类型:
$ innodb_space -f test/e.ibd space-page-type-regions
start end count type
0 0 1 FSP_HDR
1 1 1 IBUF_BITMAP
2 2 1 INODE
3 3 1 INDEX
4 5 2 FREE (ALLOCATED)
该表为IBD空间文件分配了标准页:FSP_HDR、IBUF_BITMAP、INODE和(空)索引的根索引页。还有两个未使用的空闲(已分配)页面。
space-lists模式可以用于汇总空间中的区段描述符和inode列表:
$ innodb_space -f test/e.ibd space-lists
name length f_page f_offset l_page l_offset
free 0 0 0 0 0
free_frag 1 0 158 0 158
full_frag 0 0 0 0 0
full_inodes 0 0 0 0 0
free_inodes 1 2 38 2 38
只有free_frag区段描述符有全部的列,并且其中只有一个区段。free_inodes列表中只有一个INODE页面。
free_frag列表的内容可以使用space-list-iterate模式进行检测,该模式将打印输出一个图形,说明一个区段列表中所有区段内页面的使用情况("#“表示该页面已被使用,”."表示该页面是空闲的):
$ innodb_space -f test/e.ibd -L free_frag space-list-iterate
start_page page_used_bitmap
0 ####............................................................
空间中所有索引中的文件段可以用space-indexes模式进行汇总:
$ innodb_space -f test/e.ibd space-indexes
id root fseg used allocated fill_factor
16 3 internal 1 1 100.00%
16 3 leaf 0 0 0.00%
只有内部文件段分配了页,并且它只有一个分配的页。index-fseg-internal-lists模式将汇总内部文件段中的区段列表:
$ innodb_space -f test/e.ibd -p 3 index-fseg-internal-lists
name length f_page f_offset l_page l_offset
free 0 0 0 0 0
not_full 0 0 0 0 0
full 0 0 0 0 0
这三个列表都是空的,因为这个空表没用分配任何完整的区段,那么使用过的page去哪了呢?那是一个片段页面,可以通过index-fseg-internal-frag-pages 列出。
$ innodb_space -f test/e.ibd -p 3 index-fseg-internal-frag-pages
page index level data free records
3 16 0 0 16252 0
这是一个最小的状态,大部分情况下是空的账簿结构和一个索引页。让我们看看一个包含一些真实数据的表:
一个有100万行的表
在对innodb_ruby的简要介绍中,我创建了一个包含100万行的表。我们将在这里的示例中使用相同的表。
总共有2,165页,其中大多数类型索引作为一个典型的表将是:
$ innodb_space -f test/t.ibd space-page-type-regions
start end count type
3 37 35 INDEX
38 63 26 FREE (ALLOCATED)
64 2188 2125 INDEX
2189 2239 51 FREE (ALLOCATED)
2240 2240 1 INDEX
2241 2303 63 FREE (ALLOCATED)
2304 2304 1 INDEX
2305 2367 63 FREE (ALLOCATED)
2368 2368 1 INDEX
2369 2431 63 FREE (ALLOCATED)
2432 2432 1 INDEX
2433 2495 63 FREE (ALLOCATED)
2496 2496 1 INDEX
2497 2687 191 FREE (ALLOCATED)
注意,在索引页块之间存在一些分配(空闲)页的间隙。InnoDB不能保证它按顺序使用空闲页面,很多关于批量数据加载的优化会导致页面被打乱顺序使用。(更多关于页面分割和这些优化将在以后的文章中介绍。)
看看这个space的列表,实际上有一些区段是空闲的,通常也有一个区段是free_frag:
$ innodb_space -f test/t.ibd space-lists
name length f_page f_offset l_page l_offset
free 2 0 1758 0 1798
free_frag 1 0 158 0 158
full_frag 0 0 0 0 0
full_inodes 0 0 0 0 0
free_inodes 1 2 38 2 38
空闲区段描述符列表中的页面都是空闲的,如预期的那样:
$ innodb_space -f test/t.ibd -L free space-list-iterate
2560 ................................................................
2624 ................................................................
free_frag范围描述符列表显示了一些“片段”页面被使用:
$ innodb_space -f test/t.ibd -L free_frag space-list-iterate
start_page page_used_bitmap
0 ######################################..........................
索引文件段显示了分配给叶文件段的页面,这也是预期的(B+树中只有3个非叶内部页面来管理2,137个叶页面):
$ innodb_space -f test/t.ibd space-indexes
id root fseg used allocated fill_factor
15 3 internal 3 3 100.00%
15 3 leaf 2162 2528 85.52%
你还可以看到,叶的索引文件段分配的页面多余它实际使用的页,显示了85.52%的填充因子,这是由于InnoDB的片段填充因子。他在库存MySQL中固定为87.5%,现在这个值你可以自行配置,这要归功于FackeBook的MysqlBug 64673。
由于内部索引文件段只有3个页面,正如预期的那样,文件段列表都是空的:
$ innodb_space -f test/t.ibd -p 3 index-fseg-internal-lists
name length f_page f_offset l_page l_offset
free 0 0 0 0 0
not_full 0 0 0 0 0
full 0 0 0 0 0
这三个使用的页面被分配为片段页:
$ innodb_space -f test/t.ibd -p 3 index-fseg-internal-frag-pages
page index level data free records
3 15 2 26 16226 2
36 15 1 14521 1401 1117
37 15 1 13585 2341 1045
叶索引文件段列表显示非常繁忙,有32个完整的区段和6个不完整的区段:
$ innodb_space -f test/t.ibd -p 3 index-fseg-leaf-lists
name length f_page f_offset l_page l_offset
free 0 0 0 0 0
not_full 6 0 1518 0 1718
full 33 0 198 0 1478
此外,叶索引文件段已经分配了所有可能的32个片段页(在以上任何完整区段之前):
$ innodb_space -f test/t.ibd -p 3 index-fseg-leaf-frag-pages
page index level data free records
4 15 0 9812 6286 446
5 15 0 15158 860 689
6 15 0 10912 5170 496
7 15 0 10670 5412 485
8 15 0 12980 3066 590
9 15 0 11264 4808 512
10 15 0 4488 11690 204
11 15 0 9680 6418 440
12 15 0 9306 6800 423
13 15 0 9658 6434 439
14 15 0 10032 6062 456
15 15 0 9988 6108 454
16 15 0 9570 6530 435
17 15 0 9130 6978 415
18 15 0 8844 7266 402
19 15 0 11770 4300 535
20 15 0 9020 7092 410
21 15 0 8646 7462 393
22 15 0 9746 6354 443
23 15 0 11066 5014 503
24 15 0 8910 7204 405
25 15 0 11748 4322 534
26 15 0 10978 5094 499
27 15 0 11132 4940 506
28 15 0 9350 6750 425
29 15 0 13508 2526 614
30 15 0 14938 1082 679
31 15 0 14520 1506 660
32 15 0 9086 7016 413
33 15 0 9724 6368 442
34 15 0 10978 5102 499
35 15 0 9504 6592 432
完整的区段,如预期的,都是满的:
$ innodb_space -f test/t.ibd -p 3 -L full index-fseg-leaf-list-iterate
start_page page_used_bitmap
64 ################################################################
128 ################################################################
192 ################################################################
256 ################################################################
320 ################################################################
384 ################################################################
448 ################################################################
512 ################################################################
576 ################################################################
640 ################################################################
704 ################################################################
768 ################################################################
832 ################################################################
896 ################################################################
960 ################################################################
1024 ################################################################
1088 ################################################################
1152 ################################################################
1216 ################################################################
1280 ################################################################
1344 ################################################################
1408 ################################################################
1472 ################################################################
1536 ################################################################
1600 ################################################################
1664 ################################################################
1728 ################################################################
1792 ################################################################
1856 ################################################################
1920 ################################################################
1984 ################################################################
2048 ################################################################
2112 ################################################################
正如预期的那样,not_full区段全部被部分填充:
$ innodb_space -f test/t.ibd -p 3 -L not_full index-fseg-leaf-list-iterate
start_page page_used_bitmap
2176 #############...................................................
2240 #...............................................................
2304 #...............................................................
2368 #...............................................................
2432 #...............................................................
2496 #...............................................................
你可以在这里看到InnoDB的页面分割优化:为了在磁盘上按顺序排列数据,它已经多次将第一个页面移出(这是由于页号的“暗示”,这是不确定的)。未来将对这种行为进行更深入的研究。