索引是为了快速检索和定位数据行而创建的一种数据结构。索引是由表中索引列数据进行排序后的集合和指向这些值的物理标识(例如:ROWID 等聚集索引键)共同组成。在 DM 中,除了位图索引、位图连接索引、全文索引和空间索引外,索引数据都采用 B+ 树结构进行存储,在 DM 手册的其余地方都简称为 B 树。索引和表一样需要存储空间。
索引相当于一本书的目录,根据目录中的页码标识快速检索并定位到的查找内容。
索引可使 SQL 语句快速地定位到相关数据记录上。除了系统自动创建的聚集索引以外,其它索引均为可选项。
创建或删除一个索引,不会影响基表、数据库应用或其它索引。当插入、更改和删除相关表的行时,DM8 会自动管理索引。如果删除索引,所有的应用仍继续工作,但访问以前被索引了的数据时速度可能会变慢。
可以从五个角度对索引进行分类,下面分别进行介绍。
从物理存储角度进行分类,可分为聚集索引和非聚集索引。
● 聚集索引(又称为一级索引、主索引):聚集索引就是按照聚集索引键构造一棵 B+ 树,表数据存储在 B+ 树叶子节点上,通过定位索引可直接在 B+ 树中找到数据。每一个表有且只有一个聚集索引。
● 非聚集索引(又称为二级索引、辅助索引):将二级索引列和聚集索引列共同存储在 B+ 树叶子节点上。如果查找非聚集索引键值或聚集索引键值可直接在 B+ 树中找到;如果查找索引键值以外的数据,则需要回到一级索引中进行查找。每一个表可以有多个非聚集索引。
下面用一个具体的示例展示聚集索引和非聚集索引的用法。检索过程如图 10.1 所示。
从索引功能角度进行分类,可分为唯一索引、函数索引、位图索引、位图连接索引、全文索引、空间索引、数组索引、普通索引。
● 唯一索引:索引数据根据索引键唯一;
● 函数索引:包含函数/表达式的预先计算的值;
● 位图索引:对低基数的列创建位图索引;
● 位图连接索引:针对两个或者多个表连接的位图索引,主要用于数据仓库中;
● 全文索引:在表的文本列上而建的索引。具体内容请参考第 18 章;
● 空间索引:在空间数据上创建的索引,专用于 DMGEO 包中;
● 数组索引:在一个只包含单个数组成员的对象列上创建的索引;
● 普通索引:除了唯一索引、函数索引、位图索引、位图连接索引、全文索引、空间索引、数组索引以外的索引,均为普通索引。
从是否存储数据的角度进行分类,可分为虚索引和实索引。
● 虚索引:指不存储数据的索引。虚索引由系统自动并隐式地创建,目的是保证约束的正确性。
系统在下述情景中会自动创建一个虚索引:
情景 1 为普通表(非 HUGE 表)创建外键引用约束且未使用 WITH INDEX 时,系统自动创建一个不含数据的虚索引。
情景 2 为非事务型 HUGE 表创建 PRIMARY KEY 主键约束或 UNIQUE 唯一约束时,系统自动创建一个不含数据的虚索引。此处需要说明一点,系统自动为 UNIQUE 约束创建的 UNIQUE 索引为虚索引,而用户手动通过 CREATE UNIQUE INDEX 语法创建的 UNIQUE 索引为实索引,同为 UNIQUE 索引但二者类型不同。
情景 3 当 DM.INI 参数 HUGE_UNIQUE_CHECK=0,为事务型 HUGE 表创建 PRIMARY KEY 主键约束或 UNIQUE 唯一约束时,系统自动创建一个不含数据的虚索引。
下面用具体的示例展示系统创建的虚索引。
例 1 展示引用约束对应的虚索引。
例 2 展示 HUGE 表主键约束对应的虚索引。
● 实索引:指存储数据的索引。虚索引以外的索引均为实索引。
从索引键值的个数进行分类,可分为单列索引和复合索引。
● 单列索引:只有一个索引键的索引。
● 复合索引:含有多个索引键的索引。
从分区的角度进行分类,可分为全局索引和局部索引。全局索引和局部索引均为二级索引,专门用于水平分区表中。
当分区子表个数较多、索引列的选择率较好、没有使用分区裁剪优化等因素时,执行计划会倾向于使用全局索引进行查询。但由于全局索引的日常维护成本高于局部索引。因此用户可根据实际应用场景权衡利弊之后再在全局索引和局部索引中进行选择。
● 全局索引:全局索引是以整张表的数据为对象而建立的索引。
指定 GLOBAL 关键字创建的索引即为全局索引。创建全局索引时,会在水平分区表的主表上创建全局索引和在每个子表上创建全局本地索引。索引数据存储在全局索引上。全局本地索引的命名规则为:INDEX+ 全局本地索引 ID_全局索引 ID。例如:全局索引 IDX1 的 ID 为 3504,全局本地索引的 ID 为 3506,那么全局本地索引的名称为 INDEX3506_3504。
全局索引具体分为两种:全局非分区索引和全局分区索引。指定了 <PARTITION 子句 > 的索引即为分区索引。只有 DMDPC 功能支持分区索引。
全局非分区索引可用于除 DMDPC 以外的任何环境中。
例 1 创建全局非分区索引
全局分区索引专门用于 DMDPC 环境中。索引经 <PARTITION 子句 > 分区之后,全局索引便有了分区子索引。索引数据存储在分区子索引上。
分区子索引的命名规则为:全局索引名_索引分区名。例如:全局索引名称为 IDX1,索引分区名为 P1、P2,那么分区子索引名称为 IDX1_P1 和 IDX1_P2。
分区子索引是全局分区索引的组成部分,使用全局索引即可使用到分区子索引。不支持单独使用分区子索引进行查询。
例 2 在 DMDPC 环境中创建全局分区索引
● 局部索引:局部索引是在分区表的每个分区上创建的索引。
未指定 GLOBAL 关键字创建的索引即为局部索引。局部索引暂时不支持分区。创建局部索引时,会在水平分区表的主表上创建局部索引和在每个子表上创建子表局部索引。索引数据存储在子表局部索引上。
子表局部索引的命名规则为:INDEX+ 子表局部索引 ID_局部索引 ID。例如:局部索引 IDX1 的 ID 为 3504,子表局部索引的 ID 为 3506,那么子表局部索引的名称为 INDEX3506_3504。
例 创建局部索引
索引是与表相关的可选的结构(聚集索引除外),它能使对应于表的 SQL 语句执行得更快,因为有索引比没有索引能更快地定位信息。DM8 索引能提供访问表的数据的更快路径,可以不用重写任何查询而使用索引,其结果与不使用索引是一样的,但速度更快。
DM8 提供了几种最常见类型的索引,对不同场景有不同的功能,它们是:
- 聚集索引:每一个普通表有且只有一个聚集索引;
- 唯一索引:索引数据根据索引键唯一;
- 函数索引:包含函数/表达式的预先计算的值;
- 位图索引:对低基数的列创建位图索引;
- 位图连接索引:针对两个或者多个表连接的位图索引,主要用于数据仓库中;
- 全文索引:在表的文本列上而建的索引。具体内容请参考第 19 章。
索引在逻辑上和物理上都与相关的表的数据无关,作为无关的结构,索引需要存储空间。创建或删除一个索引,不会影响基本的表、数据库应用或其他索引。当插入、更改和删除相关的表的行时,DM8 会自动管理索引。如果删除索引,所有的应用仍继续工作,但访问以前被索引了的数据时速度可能会变慢。
一般情况下,在插入或装载了数据后,为表创建索引会更加有效率。如果在装载数据之前创建了一个或多个索引,那么在插入每行时 DM8 都必须更改和维护每个索引,使得插入效率降低。
使用下面的准则来决定何时创建索引:
- 如果需要经常地检索大表中的少量的行,就为查询键创建索引;
- 为了改善多个表的连接的性能,可为连接列创建索引;
- 主键和唯一键自动具有索引,在外键上很多情况下也创建索引;
- 小表不需要索引。
选取表中的索引列时可以考虑以下几点:
- 列中的值相对比较唯一 ;
- 取值范围大,适合建立索引;
- CLOB 和 TEXT 只能建立全文索引、BLOB 不能建立任何索引。
在 CREATE INDEX 语句中列的排序会影响查询的性能。通常,将最常用的列放在最前面。
如果查询中有多个字段组合定位,则不应为每个字段单独创建索引,而应该创建一个组合索引。当两个或多个字段都是等值查询时,组合索引中各个列的前后关系是无关紧要的。但是如果是非等值查询时,要想有效利用组合索引,则应该按等值字段在前,非等值字段在后的原则创建组合索引,查询时只能利用一个非等值的字段。
一个表可以有任意数量的索引。但是,索引越多,修改表数据的开销就越大。当插入或删除行时,表上的所有索引也要被更改;更改一个列时,包含该列的所有索引也要被更改。因此,在从表中检索数据的速度和更新表的速度之间有一个折衷。例如,如果一个表主要仅用于读,则索引多就有好处;如果一个表经常被更新,则索引不宜多建。
创建索引之前先估计索引的大小能更好地促进规划和管理磁盘空间。可以用索引以及回滚段、重做日志文件的组合估计的大小来决定支持所期望的数据库所需的磁盘空间的大小。通过这些估计,就可以购买合适的硬件和做出其他正确的决定。
用单个索引估计的大小能更好地管理索引使用的磁盘空间。创建索引时,可以设置适当的存储参数,并改善使用该索引的应用的 I/O 性能。例如,假设在创建索引之前估计索引的最大大小,之后就可以在创建该索引时设置适当的存储参数,就能很少为表的数据段分配簇。并且,所有的该索引的数据都被保存在相对连续的磁盘空间扇区中,这就减少了使用该索引的磁盘 I/O 操作所需的时间。
可以在除临时表空间、日志表空间和回滚段表空间外的其他任何表空间中创建索引,也可以在其索引的表的相同或不同的表空间中创建索引。如果表及其索引使用相同的表空间 能更方便地对数据库进行管理(如表空间或文件备份)或保证应用的可用性,因为所有有关的数据总是在一起联机。然而,将表及其索引放在不同的表空间(在不同磁盘上)产生的性能比放在相同的表空间更好,因为这样做减少了磁盘竞争。但是将表及其索引放在不同的表空间时,如果一个表上某索引所在的表空间脱机了,则涉及这张表的 SQL 语句可能由于执行计划仍旧需要使用被脱机的索引而不能成功执行。
本节描述如何创建索引。要在用户自己的模式中创建索引,至少要满足如下条件之一:
- 要被索引的表是在自己的模式中 ;
- 在要被索引的表上有 CREATE INDEX 权限;
- 具有 CREATE ANY INDEX 数据库权限。
要在其他模式中创建索引,用户必须具有 CREATE ANY INDEX 数据库权限。
可以用 CREATE INDEX 语句显式地创建索引。
例 在 emp 表的 ename 列上创建一个名为 emp_ename 的索引,该索引使用表空间 users
上述语句为该索引显式地指定了几个存储设置和一个表空间。如果没有给索引指定存储选项,则 INITIAL 和 NEXT 等存储选项会自动使用表空间的默认存储选项。
下面介绍几种常见索引的显式创建方法。
DM8 中表(列存储表和堆表除外)都是使用 B 树索引结构管理的,每一个普通表都有且仅有一个聚集索引,数据都通过聚集索引键排序,根据聚集索引键可以快速查询任何记录。
当建表语句未指定聚集索引键时,DM8 的默认聚集索引键是 ROWID。若指定索引键,表中数据都会根据指定索引键排序。
建表后,DM8 也可以用创建新聚集索引的方式来重建表数据,并按新的聚集索引排序。
例 可以对 emp 表以 ename 列新建聚集索引
新建聚集索引会重建这个表以及其所有索引,包括二级索引、函数索引,是一个代价非常大的操作。因此,最好在建表时就确定聚集索引键,或在表中数据比较少时新建聚集索引,而尽量不要对数据量非常大的表建立聚集索引。
创建聚集索引的约束条件:
- 每张表中只允许有一个聚集索引,如果之前已经指定过 CLUSTER INDEX 或者指定了 CLUSTER PK,则用户新建立 CLUSTER INDEX 时系统会自动删除原先的聚集索引。但如果新建聚集索引时指定的创建方式(列,顺序)和之前的聚集索引一样,则会报错;
- 指定 CLUSTER INDEX 操作需要重建表上的所有索引,包括 PK 索引;
- 删除聚集索引时,缺省以 ROWID 排序,自动重建所有索引;
- 若聚集索引是默认的 ROWID 索引,不允许删除;
- 聚集索引不能应用到函数索引中;
- 不能在列存储表和堆表上新建聚集索引;
- 建聚集索引语句不能含有 partition_clause 子句;
- 在临时表上增删索引会使当前会话上临时 b 树数据丢失;
- 不支持在含有多媒体类型的表上新建聚集索引。
索引可以是唯一的或非唯一的。唯一索引可以保证表上不会有两行数据在键列上具有相同的值,非唯一索引不会在键列上施加这个限制。
可用 CREATE UNIQUE INDEX 语句来创建唯一索引。
例 创建一个唯一索引
用户可以在希望的列上定义 UNIQUE 完整性约束,DM8 通过自动地在唯一键上定义一个唯一索引来保证 UNIQUE 完整性约束。
基于函数的索引促进了限定函数或表达式的返回值的查询,该函数或表达式的值被预先计算出来并存储在索引中。正确使用函数索引,可以带来以下好处:
- 创建更强有力的分类,例如可以用 UPPER 和 LOWER 函数执行区分大小写的分类;
- 预先计算出计算密集的函数的值,并在索引中将其分类。可以在索引中存储要经常访问的计算密集的函数,当需要访问值时,该值已经计算出来了。因此,极大地改善了查询的执行性能;
- 增加了优化器执行范围扫描而不是全表扫描的情况的数量。
例 考虑如下 WHERE 子句中的表达式
因为该索引是建立在 column_a + column_b 之上的,所以优化器可以为该查询使用范围扫描。优化器根据该索引计算查询代价,如果代价最少,优化器就会选择该函数索引,column_a + column_b 就不会重复计算。
创建函数索引有以下约束条件:
- 表达式不允许为时间间隔类型;
- 表达式中不允许出现半透明加密列;
- 函数索引表达式的长度理论值不能超过 816 个字符(包括生成后的指令和字符串);
- 函数索引不能为 CLUSTER 或 PRIMARY KEY 类型;
- 表达式不支持集函数和不确定函数,不确定函数为每次执行得到的结果不确定,系统中不确定函数包括:RAND、SOUNDEX、CURDATE、CURTIME、CURRENT_DATE、CURRENT_TIME、CURRENT_TIMESTAMP、GETDATE、NOW、SYSDATE、CUR_DATABASE、DBID、EXTENT、PAGE、SESSID、UID、USER、VSIZE、SET_TABLE_OPTION、SET_INDEX_OPTION、UNLOCK_LOGIN、CHECK_LOGIN、GET_AUDIT、CFALGORITHMSENCRYPT、SF_MAC_LABEL_TO_CHAR、CFALGORITHMSDECRYPT、BFALGORITHMSENCRYPT、SF_MAC_LABEL_FROM_CHAR、BFALGORITHMSDECRYPT、SF_MAC_LABEL_CMP;
- 快速装载不支持含有函数索引的表;
- 若函数索引中要使用用户自定义的函数,则函数必须是指定了 DETERMINISTIC 属性的确定性函数;
- 若函数索引中使用的确定性函数发生了变更或删除,用户需手动重建函数索引;
- 若函数索引中使用的确定性函数内有不确定因素,会导致前后计算结果不同的情况。在查询使用函数索引时,使用数据插入函数索引时的计算结果为 KEY 值;修改时可能会导致在使用函数索引过程中出现根据聚集索引无法在函数索引中找到相应记录的情况,对此进行报错处理;
- 临时表不支持函数索引。
位图索引主要针对含有大量相同值的列而创建。位图索引被广泛引用到数据仓库中,创建方式和普通索引一致,对低基数(不同的值很少)的列创建位图索引,能够有效提高基于该列的查询效率。且执行查询语句的 where 子句中带有 AND 和 OR 谓词时,效率更加明显。
例 创建一个位图索引
位图索引具有以下约束:
- 支持普通表、堆表和水平分区表创建位图索引;
- 不支持对大字段创建位图索引;
- 不支持对计算表达式列创建位图索引;
- 不支持在 UNIQUE 列和 PRIMARY KEY 上创建位图索引;
- 不支持对存在 CLUSTER KEY 的表创建位图索引;
- 仅支持单列或者不超过 63 个组合列上创建位图索引;
- MPP 环境下不支持位图索引的创建;
- 不支持全局位图索引;
- 包含位图索引的表不支持并发的插入、删除和更新操作;
- 不支持在间隔分区表上创建位图索引。
位图连接索引是一种提高通过连接实现海量数据查询效率的有效方式,主要用于数据仓库环境中。区别于上一节所说的建立在单表上的位图索引,位图连接索引是针对两个或者多个表的连接而建立的位图索引,同时保存了连接的位图结果。对于索引列中的每一个值,位图连接索引在索引表中保存了对应行的 ROWID。
例 创建一个位图连接索引
使用说明
- 适用于常规索引的基本限制也适用于位图连接索引;
- 用于连接的列必须是维度表中的主键或存在唯一约束;如果是复合主键,则必须使用复合主键中的所有列;
- 当多个事务同时使用位图连接索引时,同一时间只允许更新一个表;
- 连接索引创建时,基表只允许出现一次;
- 不允许对存在 cluster key 的表创建位图连接索引;
- 位图连接索引表(内部辅助表,命名为 BMJ$_索引名)仅支持 select 操作,其他操作都不支持:如 insert、delete、update、alter、drop 和建索引等;
- 不支持对位图连接索引所在事实表和维度表的备份还原,不支持位图连接索引表的表级备份还原;
- 不支持位图连接索引表、位图连接索引以及虚索引的导出导入;
- 位图连接索引及其相关表不支持快速装载;
- 位图连接索引名称的长度限制为:事实表名的长度 + 索引名称长度 +6<128;
- 仅支持普通表、堆表和 HUGE 表;
- WHERE 条件只能是列与列之间的等值连接,并且必须含有所有表;
- 事实表上聚集索引和位图连接索引不能同时存在;
- 不支持对含有位图连接索引的表中的数据执行 DML,如需要执行 DML,则先删除该索引;
- 含有位图连接索引的表不支持下列 DDL 操作:删除、修改表约束,删除、修改列,修改表名。另外,含位图连接索引的堆表不支持添加列操作;
- 不允许对含有位图连接索引的表并发操作;
- 创建位图连接索引时,在存储参数中可指定存储位图的字节数,有效值为:4~2048,服务器自动校正为 4 的倍数,默认值为 128。如 STORAGE(SECTION(4)),表示使用 4 个字节存储位图信息。
隐式创建方式只支持创建唯一索引。
DM8 通过在唯一键或主键上创建一个唯一索引来在表上实施 UNIQUE KEY 或 PRIMARY KEY 完整性约束。当启用约束时 DM8 自动创建该索引。如下面的语句会自动在表 emp 的 name 列上创建一个唯一索引。此处隐式创建的唯一索引是包含索引数据的实索引。
例 创建 PRIMARY KEY 约束时,系统会隐式地自动在表 T1 的 C1 列上创建一个唯一索引
如果 SQL 语句想使用某一个索引,则 SQL 语句的查询项和 WHERE 子句的过滤项中必须包含该索引的全部索引键。当同时包含了多个索引的索引键时,系统会选择一个最优的索引进行查询。例如:SQL 语句“SELECT A FROM T WHERE B=1; ”会使用建立在(A,B)列上的索引。
总体来说,最少的查找即可得到所需数据,即为最优索引。
下面用具体的示例进行介绍。
数据准备:
例 1 使用聚集索引 S21
例 2 使用非聚集索引 S22
查询语句想使用索引 S22,则 SELECT 查询项和 WHERE 子句过滤项需包含 S22 的全部索引键 NAME 和 DEPARTMENT。
例 3 先使用非聚集索引 S23,再使用聚集索引
首先,在 SSEK 中使用 S23 非聚集索引进行扫描定位,得到 NAME;
其次,因为 SELECT * 中查询项太多,需要在 BLKUP2 中通过 S23 回到聚集索引上进行二次查找,得到*中的其它数据。
当一个表经过大量的增删改操作后,表的数据在物理文件中可能存在大量碎片,从而影响访问速度。另外,当删除表的大量数据后,若不再对表执行插入操作,索引所处的段可能占用了大量并不使用的簇,从而浪费了存储空间。
可以使用重建索引来对索引的数据进行重组,使数据更加紧凑,并释放不需要的空间,从而提高访问效率和空间效率。DM8 提供的重建索引的系统函数为:
SCHNAME 为索引所在的模式名,INDEXID 为索引 ID。
使用说明:
- 水平分区子表,临时表和系统表上建的索引不支持重建
- 虚索引和聚集索引不支持重建
例 需要重建索引 emp_name,假设其索引 ID 为 ,那么使用以下语句重建索引:
用户可能出于以下某项原因需要删除一个索引:
- 不再需要该索引;
- 该索引没有为针对其相关的表所发布的查询提供所期望的性能改善。例如,表可能很小,或者尽管表中有许多行但只有很少的索引项;
- 应用没有用该索引来查询数据。
要想删除索引,则该索引必须包含在用户的模式中或用户必须具有 DROP ANY INDEX 数据库权限。索引删除之后,该索引的段的所有簇都返回给包含它的表空间,并可用于表空间中的其他对象。
如何删除索引,取决于该索引是否是通过 CREATE INDEX 语句明确创建的,是则可以用 DROP INDEX 语句删除该索引。
例 1 下面的语句删除 emp_ename 索引
删除不存在的索引会报错。若指定 IF EXISTS 关键字,删除不存在的索引,不会报错,例如:
然而,不能直接删除与已启用的 UNIQUE KEY 键或 PRIMARY KEY 键约束相关的索引。要删除一个与约束相关的索引,必须停用或删除该约束本身。
例 2 下面的语句删除主键约束 pk_emp_name,同时删除其对应的索引
除了删除普通索引,DM8 还提供删除聚集索引,只要其聚集索引是通过 CREATE CLUSTER INDEX 明确建立的。
例 3 下面的语句删除 emp 表的聚集索引 clu_emp_name
删除聚集索引其实是使用 ROWID 作为索引列重建聚集索引,即跟新建聚集索引一样会重建这个表以及其所有索引。
删除表就自动删除了所有与其相关的索引。
创建索引后,可以通过 INDEXDEF 系统函数查看索引的定义。
INDEXID 为索引 ID,PREFLAG 表示返回信息中是否增加模式名前缀,1 表示导出模式名;0 表示只导出对象名。
例 需要查看索引 emp_name 的定义,假设其索引 ID 为 ,那么使用以下语句查看索引定义
到此这篇返回上级目录可选用(返回上级目录可选用什么字段)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/27215.html