MySQL把表的数据词典信息以.frm文件的形式存在数据库目录里,所有MySQL存储引擎都是这样的。但是每个InnoDB表在表空间内的InnoDB内部数据词典里也有它自己的条目。当MySQL移除表或数据库,它不得不删除.frm文件和InnoDB数据词典内的相应条目。这就是为什么你
MySQL把表的数据词典信息以.frm文件的形式存在数据库目录里,所有MySQL存储引擎都是这样的。但是每个InnoDB表在表空间内的InnoDB内部数据词典里也有它自己的条目。当MySQL移除表或数据库,它不得不删除.frm文件和InnoDB数据词典内的相应条目。这就是为什么你不能在数据库之间简单地移动.frm文件来移动InnoDB表。
每个InnoDB有一个叫聚集索引(clustered index)的特殊索引,行的数据被存于其中。
通过聚集索引访问行速度很快,因为行数据与索引扫描头部在同一数据页上。如果表是巨大的,当对于那些索引与数据放在不同数据页上的方案,聚集索引构架通常更节约磁盘I/O。(比如,MyISAM用一个文件存放数据,另外一个文件存放索引)。
在InnoDB中,非聚集索引里的记录(也称为辅助索引或第二索引)包含对应行的主键值。InnoDB用这个主键值从聚集索引中搜索行。注意,如果主键比较长,第二索引就会使用更多空间,因此最好使用一个比较短的主键。
所有InnoDB的索引是B树索引,这种索引记录被存储在树的叶子页上。一个索引页的默认大小是16KB。当新记录被插入,InnoDB会为将来索引记录的插入和更新留下十六分之一的页空间。
如果索引记录以连续的顺序被插入(升序或者降序),结果索引页大约是15/16满。如果记录被以随机的顺序被插入,页面是从1/2到 15/16满。如果索引页的填充因子降到低于1/2,InnoDB会收缩索引树来释放页。
在数据库应用中,主键是一个唯一的识别符,并且新行被以主键的升序来插入,这是个常见的情况。因此,聚集索引的插入不需要磁盘的随机读。
另一方面,第二索引通常是非唯一的,第二索引的插入顺序也相对随机。这可能会导致大量的随机磁盘I/O操作,而没有一个被用在InnoDB中的专用机制。
如果一个索引记录应该被插入到一个非唯一第二索引,InnoDB检查第二索引页是否在缓冲池中。如果是,InnoDB直接插入到索引页。如果索引页没有在缓冲池中被发现,InnoDB插入记录到一个专门的插入缓冲结构。插入缓冲被保持得如此小以至于它完全适合在缓冲池,并且可以非常快地做插入。
插入缓冲周期性地被合并到数据库中第二索引树里。把数个插入合并到索引树的同一页,节省磁盘I/O操作,经常地这是有可能的。据测量,插入缓冲可以提高到表的插入速度达15倍。
在插入事务被提交之后,插入缓冲合并可能连续发生。实际上,服务器关闭和重启之后,这会连续发生。
当许多第二索引必须被更新,并且许多行已被插入之时,插入缓冲合并可能需要数个小时。在这期间内,磁盘I/O将会增加,这样会导致磁盘约束查询明显缓慢。另一个明显的后台I/O操作是净化(purge)线程。
如果一个表几乎完全缓存在主内存中,在其上执行查询最快的方法就是使用哈希索引。InnoDB有一个自动机制,它监视对为一个表定义的索引的索引搜索。如果InnoDB注意到查询会从建立一个哈希索引中获益,它会自动地这么做。
注意,哈希索引总是基于表上已存在的B树索引来建立。根据InnoDB对B树索引观察的搜索方式,InnoDB会在为该B树定义的任何长度的键的一个前缀上建立哈希索引。 哈希索引可以是部分的:它不要求整个B树索引被缓存在缓冲池。InnoDB根据需要对被经常访问的索引的那些页面建立哈希索引。
在某种意义上,InnoDB通过自适应的哈希索引机制来调整自己,使其更加贴近主内存数据库的架构。
InnoDB表的物理行结构取决于表创建时指定的行格式。在MySQL 5.1中,InnoDB默认使用紧凑(COMPACT)格式,但为了保留与旧版本MySQL的兼容性,冗余(REDUNDANT)格式也可用。查看InnoDB表的行格式,可使用SHOW TABLE STATUS命令。
紧凑的行格式大约可减少20%的存储空间,但某些操作会增加CPU使用量。如果是一个典型的受限于高速缓存命中率和磁盘速度的工作负荷,使用紧凑格式可能会更快。如果是一种少见工作负荷情况,由于有限的CPU速度,紧凑格式可能会比较慢。
使用冗余行格式的InnoDB表行具有以下特点:
使用紧凑行格式的InnoDB表行具有以下特点: