管理堆表

17.1 什么是堆表

普通表都是以 B 树形式存放的,ROWID 都是逻辑的 ROWID,即从 1 一直增长下去。在并发情况下,每次插入过程中都需要逻辑生成 ROWID,这样影响了插入数据的效率;对于每一条数据都需要存储 ROWID 值,也会花费较大的存储空间。堆表就是基于上述两个理由而提出的。

简单地说,堆表是指采用了物理 ROWID 形式的表,即使用文件号、页号和页内偏移而得到 ROWID 值,这样就不需要存储 ROWID 值,可以节省空间。逻辑 ROWID 在插入或修改过程中,为了确保 ROWID 的唯一性,需要依次累加而得到值,这样就影响了效率,而堆表只需根据自己的文件号、页号和页内偏移就可以得到 ROWID,提高了效率。

普通表都是以 B 树形式存储在物理磁盘上,而堆表则采用一种“扁平 B 树”方式存储,结构如下图所示。

图 17.1 堆表存储方式.png

图17.1 堆表存储方式

采用了物理 ROWID 形式的堆表,DM 服务器内部对聚集索引进行了调整,没有采用传统 B 树结构,取而代之的是“扁平 B 树”,数据页都是通过链表形式存储。为支持并发插入,扁平 B 树可以支持最多 128 个数据页链表(最多 64 个并发分支和最多 64 个非并发分支),在 B 树的控制页中记录了所有链表的首、尾页地址。对于非并发分支,如果分支数有多个,即存在多个链表,则不同的用户登录系统之后,会依据其事务 ID 号,随机选择一条链表来对堆表进行插入操作。对于并发分支,则不同用户会选择不同的分支来进行插入,如果存在多个用户选择了同一条分支的情况,才需要等待其他用户插入结束并释放锁之后才能进行插入。在并发情况下,不同用户可以在不同的链表上进行插入,效率得到较大提升。

17.2 创建堆表

堆表的创建有两种方式,一种是采用在配置文件 dm.ini 中设置参数,一种是在建表语句中显式指定堆表选项。

  1. INI 参数方式

用户可以在配置文件中,添加 LIST_TABLE 参数:
1)如果 LIST_TABLE = 1,则在未显式指定表是否为堆表或非堆表时,默认情况下创建的表为堆表;
2)如果 LIST_TABLE = 0,则在未显式指定表是否为堆表或非堆表时,默认情况下创建的表为普通表形式。

用户可以在配置文件中,添加 LIST_TABLE_BRANCH 参数和 LIST_TABLE_NON_BRANCH 参数:
1)如果 LIST_TABLE_BRANCH = 0,模式为 NOBRANCH;
2)如果 LIST_TABLE_NON_BRANCH = 0 且 LIST_TABLE_BRANCH = N(N 非 0),模式为 BRANCH N;
3)如果 LIST_TABLE_NON_BRANCH = M(M 非 0)且 LIST_TABLE_BRANCH = N(N 非 0),模式为 BRANCH(N,M)。

  1. SQL 语句显式指定

不管参数 LIST_TABLE 设置为何值,创建表时可以在 STORAGE 选项中指定需要创建的表形式, 与堆表创建形式相关的关键字有三个,分别是 NOBRANCH、BRANCH、CLUSTERBTR。

分支数目主要用于插入场景中。适当提高分支数量可有效地提升并发数据处理效率,但是分支过多又会加重扫描的负担,因此,合适的 <BRANCH 数 > 和 <NOBRANCH 数 > 值需用户根据实际情况来决定。<BRANCH 数 > 主要在 FLDR 导入和查询插入等并发、批量插入场景中使用;<NOBRANCH 数 > 在非并发、单行插入场景中使用。

详细语法形式参见《DM8_SQL 语言使用手册》。

1)NOBRANCH:如果指定为 NOBRANCH,则创建的表为堆表,并发分支个数为 0,非并发分支个数为 1;
2)BRANCH(N,M):如果为该形式,则创建的表为堆表,并发分支个数为 N,非并发个数为 M;
3)BRANCH N:指定创建的表为堆表,并发分支个数为 N,非并发分支个数为 1;
4)CLUSTERBTR:创建的表为非堆表,即普通 B 树表。

例 下例创建的 LIST_TABLE 表有并发分支 2 个,非并发分支 4 个

CREATE TABLE LIST_TABLE(C1 INT) STORAGE(BRANCH (2,4));

17.3 堆表的限制

堆表由于其自身的特性,与普通表相比,也为自己增添了一些限制。堆表不支持以下功能:

  1. 聚集索引

堆表采用了物理 ROWID,即通过文件号、页号和页内偏移直接生成该值。这样如果我们知道了 ROWID 值,也就知道文件号、页号和页内偏移这些变量,就可以直接定位到某条记录,所以没有必要再为堆表创建聚集索引了。在创建堆表时,系统会默认创建聚集索引,该索引只是一个根页信息。显式建立聚集索引是不允许的,如果用户需要借助聚集索引主键对数据进行排序则不推荐使用堆表。

  1. 列存储

由于列存储采用了不同方式对表进行物理存储, DM 服务器暂时不支持堆表的列存储。

17.4 维护堆表

堆表在进行数据扫描过程中,有着其先天的优势。如果知道了数据记录的 ROWID,则直接可以对 ROWID 进行解码,得到该记录的文件号、页号和页内偏移,也就得到了该记录。所以建议在经常查询的列上建立二级索引,这样在进行操作中,先通过二级索引找到记录 ROWID,就可以直接找到数据,效率有较大提高。

堆表虽然支持表的 ALTER 操作,但是建议轻易不要进行此类操作。对表进行 ALTER 操作,数据记录的 ROWID 有可能发生改变,这样每次进行 ALTER 操作,都可能进行索引的重建,需要花费较多的时间。

达梦服务器支持对堆表的备份与还原操作。还原数据时,B 树数据和二级索引可以同时被还原。

17.5 查看有关堆表的信息

可以通过系统过程 SP_TABLEDEF('SCHEMA_NAME','TABLE_NAME')查看堆表的定义信息,该函数的详细信息可参考 《DM8_SQL 语言使用手册》。

微信扫码
分享文档
扫一扫
联系客服