目前的表存储方式主要分为两种:索引组织表( Index-Organized Tables) 堆表(heap-organized tables)
- oracle:默认堆表,支持索引组织表。
- mysql:只支持索引组织表,对应的索引叫做聚集索引(cluster index)。
- postgresql:只支持堆表
简单的一句话来概括两者的区别就是一种数据是有序存储(按主键id聚集),一种是无序存储。并不一定是哪一种结构更好,还是要看具体的业务适合哪种形式。
Index-Organized Tables 索引组织表
定义:
索引组织的表具有作为主B树的变体的存储组织。与其数据以无序集合(堆)存储的普通(堆组织的)表不同,以主键排序的方式将索引组织表的数据存储在B树索引结构中。索引结构中的每个叶块都存储关键字列和非关键列。对应的主键索引也叫聚集索引,其他列的索引叫secondary index,也叫做二级索引。二级索引的每条记录都包含该行的主键值,InnoDB使用这个主键值来搜索聚集索引中的行。因此,较短的主键值是有利的,可以缩小二级索引的空间。
优势:
- 主键快速随机访问,因为仅扫描索引就足够了(数据存在聚集索引中)。由于没有单独的表存储区,对表数据的更改(insert,update,delete)只更新索引就足够了。
- 如果基于主键的范围查询访问,速度很快,因为数据是聚集在一起的。
- 需要的存储空间更小,避免的主键的重复存储。而在堆表(heap-organized tables)中主键是存储两次的。
聚集索引 clustered index
以innodb引擎举例,每个表都有一个聚集索引,其中存储行的数据。通常来讲,聚集索引与主键是一个意思。但也有特殊情况。
- 如果你没有为表定义一个primary key(意味着数据库就不知以何种形式存储数据),那么innodb将会定义第一个unique索引且其中的键列都是非null为聚集索引。
- 如果该表没有primary key或何止的unique索引,则innodb会使用一个隐藏的GEN_CLUST_INDEX(包含行ID:行ID是一个6字节的字段,随着新行的插入而单调递增。)做为聚簇索引。
聚集索引的优势在于,访问行的速度更快。因为索引中就存储数据信息。比起二级索引,都必须从根节点通过分支节点导航到正确的叶节点,以获得主键值,然后对主键索引执行随机IO读取(再次从根节点通过分支节点到正确的叶节点)来获取数据行。其实为了解决这个问题,也有covering index 这个概念,简单讲就是数据在存在于索引当中,不需要去访问表。