高性能MySQL之--聚簇索引

来源:互联网 发布:推广软件拦截 编辑:程序博客网 时间:2024/04/30 05:31

高性能MySQL之--聚簇索引

1.聚簇索引


聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。
当表有聚簇索引时,它的数据行实际上存放在索引的叶子页中。
因为无法同时把数据行存放在两个不同的对方,所以一个表只能有一个聚簇索引。

InnoDB通过主键聚集数据,
如果没有定义主键,InnoDB会选择一个唯一的的非空索引代替。
如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引。

聚集的数据有一些重要的优点:
数据访问更快,聚簇索引将索引和数据保存在同一个B-Tree中,因此从簇聚索引中获取数据通常比在非聚簇索引中查找要快。

同时,簇聚索引也有一些缺点:
更新簇聚索引列的代价很高,因为会强制InnoDB将每个被更新的列移动到新的位置;(可能有页分裂问题,也就是树的变动)

2.InnoDB和MyISAM的数据分布对比
聚簇索引和非聚簇索引的数据有区别,以及对应的主键索引和二级索引(非主键聚簇索引)的数据分布也有区别。
来看看InnoDB和MyISAM是如何存储下面这张表的:
CREATE TABLE layout_test(
col1,
col2,
primary(col1),
key(col2)
);
MyIsam的数据分布:


     图5-4:MyISAM表layout_test的数据

     图5-5:MyISAM表layout_test的主键分布

MyIsam按照数据插入的顺序存储在磁盘上。
MyIsam的主键索引与其他的索引没有什么不同,主键索引就是一个名为PRIMARY的唯一非空索引。

MyIsam的主键索引和其它列索引存储的都是索引列的值和数据行的物理地址(图中隐藏了页的物理细节)。

InnoDB的数据分布:
InnoDB实际上是“索引组织表”,因为在InnoDB中,聚簇索引就是表。
聚簇索引的每一个叶子节点包含了主键值、事务ID,用于事务和MVCC的回滚指针以及所有的剩余列。
InnoDB的二级索引和聚簇索引有很大不同。

InnoDB二级索引中存储的是主键值而不是行指针。
这样的策略减少了当出现行移动或者数据页分裂时二级索引的维护工作。




InnoDB和MyISAM的数据分布对比


可以看到innoDB主索引是聚集索引,辅助索引是非聚集,存储的是主键值 
myIsam是非聚集索引,辅助索引和主索引都是存的数据行地址

覆盖索引
通常大家设计索引都会根据查询的WHERE条件来创建合适的索引,不过这只是索引优化的一个方面。
设计优秀的索引应该考虑整个查询,而不单单是WHERE条件部分。

如果一个索引中包含了所需要查询的字段的值,我们就称为“覆盖索引”,
覆盖索引能够极大的提高性能,覆盖索引带来的好处有:
(1)索引条目远小于数据行大小,能够极大地提高性能,所以如果只需要读取索引,那么MySQL就会极大地减少数据访问量

书籍:高性能MySQL


磁盘存取

磁盘I/O涉及机械操作。磁盘是由大小相同且同轴的圆形盘片组成,磁盘可以转动(各个磁盘须同时转动)。

磁盘的一侧有磁头支架,磁头支架固定了一组磁头,每个磁头负责存取一个磁盘的内容。磁头不动,磁盘转动,

但磁臂可以前后动,用于读取不同磁道上的数据。磁道就是以盘片为中心划分出来的一系列同心环(如图标红那圈)。

磁道又划分为一个个小段,叫扇区,是磁盘的最小存储单元。

磁盘读取时,系统将数据逻辑地址传给磁盘,磁盘的控制电路会解析出物理地址,即哪个磁道哪个扇区。

于是磁头需要前后移动到对应的磁道,消耗的时间叫寻道时间,然后磁盘旋转将对应的扇区转到磁头下,消耗的时间叫旋转时间

所以,适当的操作顺序和数据存放可以减少寻道时间和旋转时间。
为了尽量减少I/O操作,磁盘读取每次都会预读,大小通常为页的整数倍。即使只需要读取一个字节,磁盘也会读取一页的数据(通常为4K)放入内存,

内存与磁盘以页为单位交换数据。

因为局部性原理认为,通常一个数据被用到,其附近的数据也会立马被用到。

 

B-Tree: 如果一次检索需要访问4个节点,数据库系统设计者利用磁盘预读原理,把节点的大小设计为一个页,

那读取一个节点只需要一次I/O操作,完成这次检索操作, 最多需要3次I/O(根节点常驻内存)。数据记录越小,

每个节点存放的数据就越多,树的高度也就越小,I/O操作就少了,检索效率也就上去了。

B+Tree:非叶子节点只存key,大大减少了非叶子节点的大小,那么每个节点就可以存放更多的记录,树更矮了,I/O操作更少了。

所以B+Tree拥有更好的性能。


0 0
原创粉丝点击