• 登录
  • Subscribe RSS Feed
 

MySQL查看InnoDB存储引擎的表和索引内部结构

09月 4, 2010

对于Oracle来说如果想了解表的内部存储情况或者SQL的执行过程,可以通过DUMP或者设置EVENT方式来获取信息。 那对于MySQL来说,如果我想看INNODB存储引擎的表和索引是怎么存储的,可以参考官方文档的《SHOW ENGINE INNODB STATUS and the InnoDB Monitors》,里面详细说明了通过创建不同的特定的表(这个方式特别怪异)来获取不同的数据。

下面就开始对文档中的内容进行学习测试:

一、创建innodb_table_monitor表

默认情况下,在MySQL中执行show engine innodb status\G命令(和show innodb status一样),是看不了表、索引的内部结构存储信息。如果要开启这个功能,就要创建一张innodb_table_monitor表。具体如下:

root@(none) 03:20:51>use test
Database changed
root@test 03:20:54>create table innodb_table_monitor(a int) engine=innodb;
Query OK, 0 rows affected (0.05 sec)

如果要停止监控的话,只要执行命令下面命令,把该表删除就可以:

drop table innodb_table_monitor;

通过上面创建好innodb_table_monitor表后,InnoDB Monitors会阶段性的每隔15秒(不过我看到的间隔是1分钟20秒)把信息打印输出到The Error Log

[mysql@xentest8-vm1 data]$ grep -v "END" xentest8-vm1.corp.alimama.com.err | grep --color "INNODB TABLE MONITOR OUTPUT"
100904 15:23:46 INNODB TABLE MONITOR OUTPUT
100904 15:25:02 INNODB TABLE MONITOR OUTPUT
100904 15:26:22 INNODB TABLE MONITOR OUTPUT
100904 15:27:42 INNODB TABLE MONITOR OUTPUT

不过,要注意的是如果没有及时删除这张表,那么The Error Log以后将会非常的大。

二、创建表,对输出信息进行分析

创建一张测试表test_1,不包含主键,并插入数据。

root@test 03:48:53>create table test_1(col_1 int) engine=innodb;
Query OK, 0 rows affected (0.00 sec)
root@test 03:53:19>select count(*) from test_1;
+----------+
| count(*) |
+----------+
|  1048576 |
+----------+
1 row in set (0.69 sec)
root@test 03:54:36>show table status like 'test_1'\G
*************************** 1. row ***************************
Name: test_1
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 1049037             -- 这是一个估算的值,并不精确
Avg_row_length: 32
Data_length: 34144256
Max_data_length: 0
Index_length: 0
Data_free: 53477376
......

下面看一下The Error Log中的数据:

其中输出结构的开始部分会包含2张内部数据字典表用于维护外键的信息,表名为SYS_FOREIGN、SYS_FOREIGN_COLS,这2张表详细信息见下图。

剩下的每张用户创建的InnoDB Table都能够在里面查到。我们详细看一下刚才我们创建的test_1表:

--------------------------------------
TABLE: name test/test_1, id 0 29, columns 4, indexes 1, appr.rows 1049037

-- 可以在name后面看到表名(格式:db_name/tbl_name format except for internal tables)
-- 表对应的id,表中有4列(其中我们定义的只有1列),有1个索引(非我们自己创建的),大概有1049037行(和show table status中的值一样)

COLUMNS:
col_1: DATA_INT DATA_BINARY_TYPE len 4;
DB_ROW_ID: DATA_SYS prtype 256 len 6;
DB_TRX_ID: DATA_SYS prtype 257 len 6;
DB_ROLL_PTR: DATA_SYS prtype 258 len 7;

-- 这边可以看到test_1(没有定义主键),内部表结构式包含4列,除了用户定义的1列外,InnoDB会在表中都隐示的加3个internal columns( Some internal columns are added by InnoDB, such as DB_ROW_ID (row ID), DB_TRX_ID (transaction ID), and DB_ROLL_PTR (a pointer to the rollback/undo data) )。每个列后面的说明见下面的【附1】。

INDEX: name GEN_CLUST_INDEX, id 0 37, fields 0/4, uniq 1, type 1
root page 16389, appr.key vals 1049037, leaf pages 2033, size pages 2084
FIELDS: DB_ROW_ID DB_TRX_ID DB_ROLL_PTR col_1

--(1) 由于没有显示的定义主键或者非空的唯一索引,InnoDB会建表的时候自动的创建名字为GEN_CLUST_INDEX的Clustered Index。(2)如果显示的定义一个主键的话,这个时候INDEX中name的值是:PRIMARY。
-- 还有索引对应的id,fields m/n (m代表用户定义索引中的列数/n代表总的索引列数,其中包含附加的internal columns)。
-- 其他具体解释见【附2】,另外FIELDS后面列出索引中的列名字。关于索引结构的测试见下面。
--------------------------------------

【附1】

• DATA_xxx: These symbols indicate the data type. There may be multiple DATA_xxx symbols for a given column.
• prtype: The column's “precise” type. This field includes information such as the column data type, character set code, nullability,signedness, and whether it is a binary string. This field is described in the innobase/include/data0type.h source file.
• len: The column length in bytes.
• prec: The precision of the type.

【附2】

• type: The index type. This is a bit field. For example, 1 indicates a clustered index and 2 indicates a unique index, so a clustered index (which always contains unique values), will have a type value of 3. An index with a type value of 0 is neither clustered nor unique. The flag values are defined in the innobase/include/dict0mem.h source file.
• root page: The index root page number.
• appr. key vals: The approximate index cardinality.
• leaf pages: The approximate number of leaf pages in the index.
• size pages: The approximate total number of pages in the index.
• FIELDS: The names of the fields in the index. For a clustered index that was generated automatically, the field list begins with the internal DB_ROW_ID (row ID) field. DB_TRX_ID and DB_ROLL_PTR are always added internally to the clustered index, following the fields that comprise the primary key. For a secondary index, the final fields are those from the primary key that are not part of the secondary index.

三、索引结构的对比

下面列表列出了无创建主键和创建主键的表的索引结构的区别:

Create Table: CREATE TABLE `test_3` (

`col_1` int(11) DEFAULT NULL,

`col_2` int(11) DEFAULT NULL,

`col_3` int(11) DEFAULT NULL,

KEY `ind_test3_col23` (`col_2`,`col_3`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1

【注释】无主键,索引列(col_2,col_3

Create Table: CREATE TABLE `test_4` (

`col_1` int(11) NOT NULL,

`col_2` int(11) DEFAULT NULL,

`col_3` int(11) DEFAULT NULL,

PRIMARY KEY (`col_1`),

KEY `ind_test4_col23` (`col_2`,`col_3`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1

【注释】主键为col_1,索引列(col_2,col_3

TABLE: name test/test_3, id 0 36, columns 6, indexes 2, appr.rows 0

-- 表中总共有6个列

COLUMNS:

col_1: DATA_INT DATA_BINARY_TYPE len 4;

col_2: DATA_INT DATA_BINARY_TYPE len 4;

col_3: DATA_INT DATA_BINARY_TYPE len 4;

DB_ROW_ID: DATA_SYS prtype 256 len 6;

DB_TRX_ID: DATA_SYS prtype 257 len 6;

DB_ROLL_PTR: DATA_SYS prtype 258 len 7;

INDEX: name GEN_CLUST_INDEX, id 0 48, fields 0/6, uniq 1, type 1

root page 20678, appr.key vals 0, leaf pages 1, size pages 1

FIELDS:  DB_ROW_ID DB_TRX_ID DB_ROLL_PTR col_1 col_2 col_3

-- fields包含所有的列

--

INDEX: name ind_test3_col23, id 0 49, fields 2/3, uniq 3, type 0

root page 20679, appr.key vals 0, leaf pages 1, size pages 1

FIELDS:  col_2 col_3 DB_ROW_ID

-- 在表无主键的情况下,创建索引,InnoDB会隐示的把DB_ROW_ID添加到最后一列。

TABLE: name test/test_4, id 0 37, columns 6, indexes 2, appr.rows 0

-- 表中总共有6个列,其中:主键列col_1DB_ROW_ID的定义不同

COLUMNS:

col_1: DATA_INT DATA_BINARY_TYPE DATA_NOT_NULL len 4;

col_2: DATA_INT DATA_BINARY_TYPE len 4;

col_3: DATA_INT DATA_BINARY_TYPE len 4;

DB_ROW_ID: DATA_SYS prtype 256 len 6;

DB_TRX_ID: DATA_SYS prtype 257 len 6;

DB_ROLL_PTR: DATA_SYS prtype 258 len 7;

INDEX: name PRIMARY, id 0 50, fields 1/5, uniq 1, type 3

root page 20676, appr.key vals 0, leaf pages 1, size pages 1

FIELDS:  col_1 DB_TRX_ID DB_ROLL_PTR col_2 col_3

-- fields包含除了DB_ROW_ID外的所有列

-- 这里不清楚对于DB_ROW_ID列和COL_1存在的区别是?

INDEX: name ind_test4_col23, id 0 51, fields 2/3, uniq 3, type 0

root page 20680, appr.key vals 0, leaf pages 1, size pages 1

FIELDS:  col_2 col_3 col_1

-- 在表存在主键的情况下:

1)如果创建不包含主键列的索引时候,InnoDB会隐示的把主键(col_1)添加到最后一列。

2)如果创建包含主键列的索引时候,这个时候索引的个数和顺序和定义索引的顺序一样。(如下)

######################################################

create index ind_test4_col213 on test_4(col_2,col_1,col_3);

INDEX: name ind_test4_col213, id 0 59, fields 3/3, uniq 3, type 0

root page 20683, appr.key vals 0, leaf pages 1, size pages 1

FIELDS:  col_2 col_1 col_3

另外对于,索引中隐藏的主键列(如上的col_1而非DB_ROW_ID),是可以被用到的,比如如下的排序查询:

posted in 其他 by Orz DBA

Follow comments via the RSS Feed | 发表评论 | Trackback URL

1 Comment to "MySQL查看InnoDB存储引擎的表和索引内部结构"

  1. orzdba wrote:

    Innodb 多版本实现
    http://www.mysqlsupport.cn/innodb-multi-version/

Leave Your Comment

 
Powered by BlogCN.com - WordPress and MySQL. Theme by Shlomi Noach, openark.org