注册
DM索引学习分享(四)-索引基础概念、聚集索引设计
专栏/今天又学了点/ 文章详情 /

DM索引学习分享(四)-索引基础概念、聚集索引设计

一笑嘴就歪 2025/10/11 271 1 0
摘要 -从索引的原理学习和讨论中,总结形成此系列文档,以做后续的进一步学习,希望也能带动你的思考。 关键词:索引,优化,索引概念,聚集索引,索引设计。

索引的基础概念

DM8的索引概念

  在达梦的《DM8数据库管理员手册》中关于索引的定义如下:
  索引是为了快速检索和定位数据行而创建的一种数据结构。索引是由表中索引列数据进行排序后的集合和指向这些值的物理标识(例如:ROWID等聚集索引键)共同组成。除了位图索引、位图连接索引、全文索引和空间索引外,索引数据都采用B+树结构进行存储,在DM手册的其余地方都简称为B树。
  经过前面的B+树原理学习,我们现在不难理解这段描述,当然这里说的索引是指二级索引,那么何为二级索引呢?有二级是不是还有一级索引?
  是的,一级索引是有的,只不过我们不称之为一级索引,我一般称为聚集索引,结合上一节中索引组织表的学习,我们就可以这样理解,聚集索引其实就是表数据集合的本身,聚集索引就是表,表就是聚集索引。
  继续结合B+树定义我们就可以引申出来,聚集索引只能有一个,即建表的时候我们显示指定一个聚集索引键后(DM8中通过CLUSTER PRIMARY KEY、CLUSTER KEY等语法来显示指定,如果没有显示指定则默认使用rowid),表数据就以该键作为B+树的内部节点键值来构建完整B+树,在叶子节点处存储所有其他列数据。
  而二级索引其实也是一个“表”,但是这个“表”的数据仅有索引列的数据加上对应行的聚集索引键值数据或指针,也就是我们上面DM8手册中的具体定义。
  我们可以通过一个表格来进行对比,并得到第一个索引的大分类聚集索引和非聚集索引:

对比维度 聚集索引 非聚集索引(二级索引)
定义 就是表数据本身,按照聚集索引键构造一棵 B+树,表数据存储在 B +树叶子节点上,通过定位索引键可直接在 B +树中找到所有数据。数据通过聚集索引键排序,根据聚集索引键可以快速查询任何记录。 独立于数据行存储的索引结构。
将二级索引列和聚集索引列共同存储在 B+ 树叶子节点上(位图索引不一定是B+树)。如果查找非聚集索引键值或聚集索引键值可直接在 B +树中找到;如果查找索引键值以外的数据,则需要回到一级索引中进行查找。数据的物理存储顺序与索引顺序无关。常见B树索引、位图索引、全文索引
数量 每个表只能有一个聚集索引 一个表可以有多个二级索引
检索过程 1、全索引扫描就 是全表扫描
2、而通过索引也可以快速定位完整数据,无需额外查询
1、全索引扫描仅扫描索引本身,代价一般比全表扫描少一点
2、通过二级索引定位索引列数据后,一般需要返回聚集索引获取其他列数据,即通常所说的回表(只有在二级索引覆盖了所有谓词和查询项时不需要回表)

  在上面的描述中会出现两个名词,索引键和主键,这个需要注意分别一下,他两是不能直接划等号的,具体区别可以参考如下图4.1

image.png
图4.1

  可以用一个具体的示例展示聚集索引和非聚集索引的用法。假设存在数据如下表

ID NAME DEPARTMENT
1 Zhang San A部
2 Li Si B部
3 Wang Wu C部
4 Chen Liu D部

  创建聚集索引和非聚集索引,并构造查询示例,分别查询聚集索引列、二级索引列、以及非索引列的情形,查询分析执行计划如下:

//创建聚集索引,索引键为 ID。
CREATE CLUSTER INDEX C1 on T1(ID);
//创建非聚集索引,索引键为 NAME。
CREATE INDEX S1 on T1(NAME);
//使用聚集索引进行查找
EXPLAIN SELECT * FROM T1 WHERE ID=2;
1 #NSET2: [1, 1, 112]
2    #PRJT2: [1, 1, 112]; exp_num(4), is_atom(FALSE)
3       #CSEK2: [1, 1, 112]; scan_type(ASC), C1(T1), scan_range[2,2]
//使用非聚集索引进行查找
EXPLAIN SELECT ID FROM T1 WHERE NAME='Wang Wu';
1 #NSET2: [1, 1, 64]
2    #PRJT2: [1, 1, 64]; exp_num(2), is_atom(FALSE)
3       #SSEK2: [1, 1, 64]; scan_type(ASC), S1(T1), scan_range['Wang Wu','Wang Wu'], 
is_global(0)
//先使用非聚集索引进行查找,再通过非聚集索引关联上聚集索引进行二次查找
EXPLAIN SELECT DEPARTMENT FROM T1 WHERE NAME='Chen Liu';

1 #NSET2: [1, 1, 96]
2    #PRJT2: [1, 1, 96]; exp_num(1), is_atom(FALSE)
3       #BLKUP2: [1, 1, 96]; S1(T1) 
4          #SSEK2: [1, 1, 96]; scan_type(ASC), S1(T1), scan_range['Chen Liu','Chen Liu'],
is_global(0)

  两者间的检索差异如图,可以看到如果sql语句的筛选条件是聚集索引键的话,一趟检索就能完成所有列数据返回,而如果是二级索引键的话,如果查询的列不止索引键和聚集索引键的话,是需要二次返回聚集索引处检索,以得到其他列数据,这个过程也是我们通常所说的"回表":

image.png
图4.2

聚集索引设计

  在前文,我们学习了聚集索引的基本概念,显而易见的,聚集索引主键的选择颇为重要。那么聚集索引主键应该如何去选择呢?
  我们不妨先回顾一些知识,聚集索引键只能有一个,它会影响到数据的存储顺序,通过聚集索引主键可以快速定位数据完整数据等等特性。
  于是在聚集索引键的选择上,我们可以基于它的这些特性,提出以下的一些基本原则,以发挥其优势方面:

特性 符合时的优点 不符合时的缺点
顺序性 1、有序写入时出现的分裂仅影响B+树尾部页和父节点链的最右路径
2、新页按顺序分配,旧页不再被修改,碎片化问题较轻
3、根据聚集索引键范围检索时,存储I/O顺序集中
1、无序写入时新数据可能插入任意位置的叶子节点,这将导致分裂事件分散在整个B+树中,导致更多页需要调整,父节点频繁更新,引发级联分裂;
2、新数据需要写入任意位置叶子节点,这也将导致存储I/O磁盘巡道时间增加
3、根据聚集索引键范围检索时,也将因为和B+树实际顺序问题导致需跨多个不连续的页读取存储I/O磁盘巡道时间增加
精简性 如果可以,让聚集索引聚集短小精简,在B+树的键值数量计算过程我们知道,键值大小将直接影响节点中可以存储的键值数量,而键长度越短,索引层级越少,查询越快。优先选择整数或短字符串。 键值过长导致内部节点存储的键值数量减少,如果表数据需要存储的比较多,最终影响整棵树层次,进而导致存储I/O增多
稳定性 如果聚集索引键很少被更新,可以减少索引的维护开销。 如果聚集索引键经常被更新,会导致数据行的移动和索引的重组,产生大量存储I/O,增加维护开销。
高频查询性 针对OLAP系统,显然查询性能更符合业务场景需求如果我们使用高频查询列作为聚集索引键,那么在利用该列进行条件定位、范围检索时可以显著提升性能。 如果我们设计的聚集索引是从来不会用来进行条件检索的列,那么聚集索引键对业务的查询性能正面作用极少

  总结这些特性,选择聚集索引键的核心是平衡查询需求、写入性能与存储效率三者关系,OLAP和OLTP系统应该各分侧重点。

(未完待续...)

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服