转载于: https://www.ywnds.com/?p=7702

一、堆表和索引组织表

NOTE

堆表也可以称之为 HOT,索引组织表也可以称之为 IOT,下面没有特别说明,两者都是一个意思。

堆(heap)组织表数据行在堆中存储,没有任何特定顺序,向一个全新的没有做过更新和删除的堆中插入一行时候,总是 append 到堆表文件的最后一页当中。因为不用考虑排序,所以插入速度会比较快。

但是要查找符合某个条件的记录,就必须得读取全部的记录以便筛选。而这个时候为了加快查询速度,索引就出现了,索引是针对少量特定字段的值拿出来进行排序存储,存储索引 key 以及数据行在堆表上面的绝对位置(页号,页内偏移),而因为索引是有序的,所以就会很容易通过索引查询到具体的记录位置(普遍使用二分查找法),然后再根据记录位置直接从表中读取该记录。同时因为索引的字段较少,所以索引通常会比其基表小得多。

从上面通过索引访问表记录的方式可以看出,当要访问的数据量较大时,通过每一条记录的位置去访问原始记录,每一条符合条件的记录都需要经过索引访问后再访问基表这样一个复杂的过程,这会花费很多时间。同样,如果不经过索引而直接查询表,也可能因为表字段太多,记录较大的情况下把全部的数据读取进来,这也会花费很多时间。

那怎么办呢?这个时候就会想到,如果表中数据本身就是有序的,这样查询表的时候就可以快速的找到符合条件的记录位置,而很容易判断符合条件记录的位置,这样只需要读取一小部分数据出来就可以了,不需要全表记录都读取出来进行判断。索引组织表就这样产生了,当然索引表中插入,更新的时候可能会因为需要排序而将数据重组,这时候数据插入或更新速度会比堆组织表慢一些。如果堆组织表上有索引,那么对堆组织表的插入也会因为要修改索引而变慢。

二、堆表和索引组织表的比较

所以,堆表的特点就是索引和数据分开,所有索引都是二级索引,或叫辅助索引。所以主键索引也是二级索引,没有完整记录,区别只有唯一或非唯一。索引中存储的是 key 与指针,指针指向具体数据记录。当然,查找 key 的算法都是一样的,使用二分查找,也叫书签查找。

跟索引组织表相比,堆表有什么好处呢?其实主要就是通过主键或二级索引查询,开销是一样的。都是通过先找到key,然后定位到数据。而索引组织表,由于二级索引是指向主键,所以查询二级索引需要先定位到 key,然后拿到主键 id,还要根据主键 id 再次通过二分查找定位到真正的数据页。当然,索引组织表通过主键查询开销与堆是一样的。从索引组织表的工作方式可以看出,索引组织表必须要有主键,如果非显式创建,InnoDB 存储引擎会默认创建一个 ROWID 当做主键;而堆表则无强制要求。

这就是经常有文章说 MyISAM 比 InnoDB 快的原因吧,但这个说法并不完全正确,索引组织表由于索引项和数据存储在一起,且 InnoDB 聚集索引各个叶子节点之间都是同过双向链表组织,且都是根据主键逻辑顺序存放,所以无论是基于主键的等值查询还是范围查询都能大大节省磁盘访问时间。特别对于范围查询,只需要定位到开始 key 的位置,就可以顺着这个位置扫描到结束key即可。如下 SQL 语句:

 
1
select * from table where id between 1000 and 2000

根据主键查时,假设主键 b+tree 高度是 3,每个叶子节点能存储 100 条记录,1000 条记录需要 10 个页。那么这个查询只需要大概 2 + 9 次 io 开销。

另外由于索引组织表的特性带来另外一个优点,举例来说,假设表 tab1(a int primary key, b int) 有两行 R1(1,2) 和 R2(2,3),那么如果 tab1 的主键索引是聚簇的 — 例如 InnoDB 就是这样 — 那么 R1 和 R2 由于其主键值是相邻的,所以在磁盘上面它们也是相邻存放的。也就是说 R1 和 R2 大概率在同一个磁盘页面上面(也可能是 R1 刚好位于一个 leaf page 的最后一行,而 R2 刚好是下一个 leaf page 的第一行,在这种情况下,我们仍然说 R1 和 R2 是相邻的),这样一次逻辑 io 查询的数据行命中率可能是 90%。

而堆表的索引只存储索引 key 以及数据行在堆表上面的绝对位置(页号,页内偏移),这样,主键值相邻的两行,它们在堆表的数据行经常位于不同的页面,除非这个表很少更新删除,并且插入的时候是按照主键值递增的顺序做 ‘append’ 型的插入的,不会后续在 pk 的已存在范围做插入。大多数 OLTP 类应用的逻辑无法满足这样苛刻的要求。这样,如果数据和查询具有局部性(通常如此),那么就无法享受到聚集索引带来的性能优势。

当然了,有序的代价也是很大的,无法 ‘append’ 插入,涉及数据重组,也就是索引页分裂与均衡。另外,如果对于索引组织表范围查询走的是二级索引,那么开销是多大呢?

如下 SQL 语句,同样是查询二级索引 1000 条记录。

 
1
select * from table where date >= 1990 limit 1000

这里假设二级索引 b+tree 高度也是 3,假设每个页子节点能存储200条键值对,这里的开销就变成了 3 + 4 + 3000 次 IO 开销了(其中3是定位到开始值的数据页,4 是扫描二级索引 1000 条数据需要扫描的页,3000 = 3*1000 表示回表到主键 1000 次产生的 IO)。这种方式也称之为回表,从二级索引回到主键。所以在这种情况下,InnoDB 很多时候都选择了直接扫描主键,也就是全表扫描,其代价可能比回表开销更小,比如在表数据页小于回表所产生的 io 次数时,因为全表扫描每个页也就一次 io 而已。这在 MySQL 5.6 之前都是这么工作的,但在 MySQL 5.6 有了 MRR 技术后,这种情况就改善了很多。

MRR 简单来说就是为每个线程开辟了一块内存空间,由 read_rnd_buffer_size 参数设置,默认 32M,把二级索引查询结果放到这块空间,并且做排序,然后利用排序后的数据进行回表,就是顺序的了。如果 mrr 内存够大,那么最快可以一次回表就拿到所有数据。当然mrr优化主要是针对磁盘的,磁盘越慢效果越好。如果你的 buffer pool 可以装下所有表数据,那么 MRR 效果其实也不大了,但一般这种情况很少。

那么堆表的缺点是什么呢?

这里我们想一下,由于堆表的索引只存储索引 key 以及数据行在堆表上面的绝对位置(页号,页内偏移),如果这行记录发生了更新,并且不能原地更新,需要进行迁移,那么就会发生一个情况,堆表所有索引都需要修改,指向新的行位置。而索引组织表就不需要这个开销,更新只会新插入变化了的索引 key,不变的索引 key 不需要新插入,只有当主键发生更改才需要对应修改其他二级索引,通常主键也不会更新,所以这也就是索引组织表更新效率更高的由来。

但一般使用堆表的数据库都不会直接这么更新,代价太大了。而是会在数据页预留一些空间,当遇见不能原地更新的记录时,就会在这个页中新插入一条更新后的记录,然后在这个页中做一个指针把老记录指向新纪录,这样就不用更新索引信息了。当然,如果你这个页中没有空闲空间可以插入新的记录,那么还是需要做行迁移,然后更新所有索引。

[转帖]堆表(HOT)和索引组织表(IOT)优缺点的更多相关文章

  1. Oracle数据库 查看表是否是 索引组织表的方法

    1. 最近在工作过程中发现 一个表插入很慢 以为是索引组织表, 所以一直有点纠结 但是发现 产品里面是没有IOT的 于是找了下公司的OCP 问了下 如何查看 就是 user_tables 视图里面的一 ...

  2. 聚集索引、非聚集索引、聚集索引组织表、堆组织表、Mysql/PostgreSQL对比、联合主键/自增长、InnoDB/MyISAM(引擎方面另开一篇)

    参考了多篇文章,分别记录,如下. 下面是第一篇的总结 http://www.jb51.net/article/76007.htm: 在MySQL中,InnoDB引擎表是(聚集)索引组织表(cluste ...

  3. MySQL InnoDB 索引组织表 & 主键作用

    InnoDB 索引组织表 一.索引组织表定义 在InnoDB存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table IOT). 在Inno ...

  4. 4. 跟踪标记 (Trace Flag) 610 对索引组织表(IOT)最小化日志

    跟踪标记:610 功能: 用批量导入操作(Bulk Import Operations)加载数据时,对于索引组织表(即有聚集索引的表) 最小化日志: 上图为simple/bulk-logged恢复模式 ...

  5. mysql之索引组织表

    1.二叉树/平衡树.B-tree.B+tree.B*tree 树:最上一层是根节点.最底下一层是叶子节点.(一般左边节点小于右边节点) 二叉树:每个节点最多只能有两个分支,一般只用于教材.二叉树的深度 ...

  6. 查找->静态查找表->分块查找(索引顺序表)

    文字描述 分块查找又称为索引顺序查找,是顺序查找的一种改进方法.在此查找算法中,除表本身外, 还需要建立一个”索引表”.索引表中包括两项内容:关键字项(其值为该字表内的最大关键字)和指针项(指示该子表 ...

  7. 查看Oracle当前用户下的信息(用户,表视图,索引,表空间,同义词,存储过程函数,约束条件)

    0.表空间 SQL>select username,default_tablespace from user_users; 查看当前用户的角色 SQL>select * from user ...

  8. 7、SQL Server索引、表压缩

    索引 什么是索引? 索引是一种磁盘上的数据结构,建立在表或视图的基础上.使用索引可以使数据的获取更快更高校,也会影响其他的一些性能,如插入或更新等. 索引主要分为两种类型:聚集索引和非聚集索引. 字典 ...

  9. Oracle大表改为分区表及表空间切换方案

    Oracle大表改为分区表及表空间切换方案 一.            背景 由于之前数据库表和索引放在一个表空间导致表空间数据文件增长太快,文件数量即将达到Oracle表空间的限制,需要对表(没有分 ...

  10. Mysql索引的类型和优缺点

    索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针.注:[1]索引不是万能的!索引可以加快数据检索操作,但会使数据修改操作变慢.每修改数据 ...

随机推荐

  1. 合宙esp32 c3 micro python 固件配置(基于thonny)

    首先,本文档是已经配置过其他esp32后发现合宙的配置需要修改一些地方. 为了让新手们减少掉坑成本,故做了一个图文指导. 准备工作: 1.thonny安装(不讲,自己去查教程) 2.esp32c3 m ...

  2. Spring MVC的生命周期与简单三大组件的简单介绍

    1.说到Spring MVC就会想到它是基于MVC设计模式的思想来设计的: 那么MVC设计模式是什么呢? 下面来介绍一下 MVC 设计模式 MVC是模型(model)-视图(view)-控制器(con ...

  3. 如何在SAP GUI中快速执行新的事务代码

    当我们成功登录SAP的某个连接后,在SAP GUI起始页(SAP轻松访问),我们可以通过点击[收藏夹]或者在界面左上角的输入框输入对应的事务代码,直接进入对应事务的界面.但是下面列举的场景,你是否知道 ...

  4. 华为云GaussDB城市沙龙活动走进安徽,助力金融行业数字化转型

    本文分享自华为云社区<华为云GaussDB城市沙龙活动走进安徽,助力金融行业数字化转型>,作者: GaussDB 数据库 . 近日,华为云GaussDB数据库城市沙龙·安徽站圈层活动顺利举 ...

  5. 用AI技术推动西安民俗文化,斗鱼超管团队有一套

    摘要:AI成为传统文化发展的助推器,助力传统文化朝着大众化.数字化.个性化.精准化方向发展,赋予传统文化新的生机,延续传统文化新的生命."斗鱼团队"从五个方面进行阐述"纵 ...

  6. 数据库技术丨GaussDB(DWS)数据同步状态查看方法

    摘要:针对数据同步状态查看方法,GaussDB(DWS)提供了丰富的系统函数.视图.工具等可以直观地对同步进度进行跟踪,尤其是为方便定位人员使用,gs_ctl工具已集合了大部分相关系统函数的调用,可做 ...

  7. 跟我学丨如何用鲲鹏服务器搭建Hadoop全分布式集群

    摘要:今天教大家如何利用鲲鹏服务器搭建Hadoop全分布式集群,动起来··· 一.Hadoop常见的三种运行模式 1.单机模式(独立模式)(Local或Standalone Mode) 默认情况下Ha ...

  8. 鸿蒙轻内核M核源码分析:数据结构之任务就绪队列

    摘要:本文会给读者介绍鸿蒙轻内核M核源码中重要的数据结构,任务基于优先级的就绪队列Priority Queue. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列三 数据结构-任务就绪队列> ...

  9. 火山引擎DataLeap数据血缘技术建设实践

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 DataLeap是火山引擎数智平台VeDI旗下的大数据研发治理套件产品,帮助用户快速完成数据集成.开发.运维.治理 ...

  10. 火山引擎DataLeap的Data Catalog系统公有云实践

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 Data Catalog是一种元数据管理的服务,会收集技术元数据,并在其基础上提供更丰富的业务上下文与语义,通常支 ...