索引表简介

索引表简介

1、索引的内部构造

因为在索引表中涉及到索引的内部构造知识,所以下面会进行简单的介绍。

首先,如果没有索引,当你想要去查找某个值的时候,你不得不对数据进行顺序扫描,如果一张表有n行,那么使用顺序扫描的平均扫描行数为n/2,一旦表的行数越来越多,这种顺序扫描的效率将大幅下降;如果有索引的参与,使用平衡树扫描的平均扫描行数为log(n),表的行数越多,这种结构带来的扫描效率并不会下降多少。所以Oracle在内部存储索引数据时,使用一种被称为平衡树的结构(B-tree)。如下图所示:

它由两部分组成:

A.      Branch blocks(树枝块):处于最顶层的树枝块又称为根树枝块(root branch blocks);这部分内容在索引一文中再做深入讨论。

B.      LeafBlocks(叶块):处于最底层的块被称为叶块(注意:之所以称为平衡树,是指:平衡树的所有叶块与根树枝块的深度都是一样的);上图是在某表的单列上建立索引;当你建立此索引时,Oracle会自动抓取此列的列值(键值)进行排序;如果是在多列上建立索引呢?Oracle对其排序是按照此列组(属性组)的键值进行排序;因为上图只有一列,那么键值就是其列值。那么,Oracle会把经过排序的列表的值分成(纵向划分)一个一个的区(一个区表示一定宽度的块的范围),这些区以双向链表的结构来组织(所谓双向链表就是一个区带有两个指针,一个指上,一个指下,如上图所示)。你可能会有疑问:那么一个叶块是不是就对应一个数据块呢?答案是否定的!一个叶块不一定就对应一个数据块,有可能一个数据块中有多个叶块,并且这些叶块在物理上不一定就邻接;也有可能某个索引的叶块在这个数据块中,而另一个叶块又在另一个数据块中。如果叶块中的数据是字符数据,那么Oracle还会自动把它们转换为对应的二进制数据(根据所指定的此数据库的字符集设置),所以上图中的叶块数据的格式还不是真正存储在数据库中的数据格式。

2、索引表

索引表使用一种平衡树(B-tree)变体(相对于上节的平衡树)来组织数据的存储(存储结构);而常规的表使用的是(也是一种数据结构)来组织数据的存储(这种数据结构是一种无序的集合)。在这里,所谓平衡树变体结构是指存储在其中的数据需要排序,并且数据的排序是按照主键排序的方式;索引表不仅像索引一样存储主键值(这里的索引指的是在表中的所有列上建立索引),而且在B-tree中的每个索引条目(上节所说的一个叶块)还存有非键值。

图5-9 一个正规表和一个索引表的比较

表5-3索引表和常规表不同的地方

Ordinary Table

Index-Organized Table

Rowid唯一标识一行。主键可指定也可不指定(因为你已经有rowid了)。

由主键来唯一标识一行。主键肯定就必须指定。

使用物理rowid,允许使用它创建二级索引。

使用逻辑rowid,允许使用它创建二级索引。

访问基于物理rowid(使用物理地址)。

访问基于逻辑rowid(使用主键,有可能使用物理猜想)。

返回所有行,使用顺序扫描。

返回所有行,使用全索引扫描。

能被存储在一个簇中。

不能被存储在一个簇中。

一列中能够含有数据类型为LONG、LOB的数据。

能含有LOB数据类型,但不能有LONG数据类型

 

小结:

如果有一张常规表,在它的所有列上创建一个索引,那么这张表和在这张表上的索引的组合就有点类似于索引表;不过,这个索引并不一定就拥有这张表所有的键值,因为这时索引的规范是:在同一个数据块中的键值只要能够被区分,那么就不必要整个键值都做存储,而只要存储键值的一部分;而索引表是存储了表中的所有键值;不过,索引表的想法就是由此开始的(因为它能提供最快速的访问)。

常规表和其索引是两个独立的存储结构,而索引表是一个单一的存储结构;

索引表的平衡树(B-tree)存储结构的条目是由<primary_Key_value,

non_primary_key_column_values>值对组成(它是使用逻辑rowids);而常规表索引的平衡树(B-tree)存储结构的条目是由<Key_value,rowid>值对组成(它是使用物理rowids)。

应用程序可以像使用常规表一样使用索引表(使用SQL语句);只不过,对索引表的操作是数据库系统内部通过操作相对应的B-tree数据结构索引来完成的。

2.1溢出(Overflow)

平衡树式的索引条目(入口)通常很小,因为对于常规表的索引来说,它们的条目仅仅包含<键值,rowid>对(在上一节总结中所举的例子是一种极端情况,只是用来理解)。然而对于索引来说,它的入口条目就比较大了,因为它必须包含整一个的行(不管你是键值还是非键值,你都得储存);这样就很有可能摧毁密集簇的平衡树索引。

Oracle提供OVERFLOW字句来处理这个问题。你能指定一个overflow表空间,如果必要,你还能把一行分成以下两个部分(一部分存储在索引中,而另一部分就存储在overflow段中):

·        索引条目包含:主键列中的主键值、一个物理rowid(也就是一个指向行溢出部分的指针)和一部分可选的非键列的值。

·        overflow部分包含:剩余的非键值。

OVERFLOW又有两个字句:PCTTHRESHOLD(阈值百分比)和INCLUDING

使用PCTTHRESHOLD你能提供一个以百分比来表示的阈值(对块的大小进行限制);如果非键列值超过了这个限制值,那么第一个非键列的值和之后的所有非键列的值都将存储在overflow段。

INCLUDING字句是让你指定某列的列名,这个列名是任意的非键列的列名,此列是出现在CREATE TABLE语句的指定列表中的列,它/它们仍然被存储在行溢出段中。不过,其它的非键列(不在INCLUDING字句中的非键列),也要遵从PCTTHRESHOLD的设置。下面是个例子:

CREATE TABLE admin_docindex2(
        token CHAR(20), 
        doc_id NUMBER,
        token_frequency NUMBER,
        token_offsets VARCHAR2(512),
        CONSTRAINT pk_admin_docindex2 PRIMARY KEY (token, doc_id))
    ORGANIZATION INDEX 
    TABLESPACE admin_tbs
    PCTTHRESHOLD 20
    INCLUDING token_frequency
OVERFLOW TABLESPACE admin_tbs2;
 
2.2二级索引(辅助索引)

索引表上的二级索引能够非常有效地访问索引表,这种索引既不是使用主键列也不是使用主键的某个前缀。Oracle构造这种索引使用的是逻辑的行标识符(logicalrowids),这种rowids是基于表的主键(而不是基于行的物理地址)。这种逻辑rowids包括了一个物理猜想(physical guess),它也是一种物理标识符(物理指针),它唯一标识行的块地址,Oracle能使用这些猜想直接对索引表的叶块进行探测,从而避免主键搜索。不过,在rowids一文中也讲过,由于索引表不拥有永久/不变的物理地址,索引这种物理猜想可能会变得陈旧/无效。

对一个常规表来说,通过一个二级索引进行访问会卷入对二级索引的一次扫描以及一个额外的I/O操作(抓取包含有目标行的数据块);对于索引表来说,通过一个二级索引的变体进行访问依赖于如何使用以及精准的物理猜想:

·        如果没有使用物理猜想,那么访问涉及到两个索引扫描:1、一次二级索引扫描2、紧随其后的一次主键索引扫描

·        如果使用有效的(精准的)物理猜想,那么访问涉及到一次二级索引扫描和一个额外的I/O操作(抓取包含有目标行的数据块,直接定位到了包含此行的数据块)

·        如果使用过期的物理猜想,呢么访问涉及到一次二级索引扫描和一个I/O操作,只不过所抓取到的数据块是错误的,紧随其后的是不得不进行一次主键索引扫描。

2.3索引表上的位图(Bitmap)索引

Oracle支持在被分割或未被分割的索引表上使用位图(bitmap)索引,创建位图索引时需要一张映射表。

2.3.1映射表(Mapping Table)

映射(mapping)表是也是一种堆组织结构的表,它存储着索引表的逻辑rowids,更进一步说,每张映射表的一行存储了索引表的一个逻辑rowids(这个rowids唯一标识索引表的一行)。因此,映射表提供了逻辑rowids和其索引表中的行的一一对应关系,并且这种映射表同样拥有物理rowids。

建立在索引表上的一个位图索引和建立在堆组织结构表上的位图索引很类似,不同的是,前者的位图索引使用的rowids是映射表中的rowids,而不是基表的。每个索引表可以拥有一张映射表,而某个索引表的所有位图都将使用一张映射表。

不管是堆表还是索引表,访问一个位图索引都是使用某个搜索键。如果这个搜索键被找到,那么根据位图的入口条目就可以找到一个物理rowid。对于堆表来说,这个物理rowid是被用来访问其基表的;而对于索引表来说,这个物理rowid是用来访问映射表的,而从索引表又可以获得一个逻辑rowid,这个逻辑rowid又是用来访问索引表的。

通过位图索引好像不会存储逻辑rowids,不过从上面可以看出,这种索引本质还是逻辑的。

注意:

行的移动不会造成位图的失效;但是,行的移动会造成映射表中的逻辑rowid中的物理猜想失效,不过索引表仍然能使用主键进行访问。

 

 

 

2.4分割索引表

你能通过在列值上使用RANGEHASHLIST分割一个索引表。这部分内容在分割一文中再做深入讨论。

2.5堆表和索引表中的UROWID类型列上的平衡树索引

数据类型为UROWID的列也可用于存储根据基于主键的逻辑rowid。Oracle支持在堆表或索引表的UROWID列上创建索引;但是只有当一个查询中谓词的条件为“等于”时,Oracle才会使用此索引,“等于”之外的谓词条件及对此列进行排序都不会使用此索引。

2.6索引表的应用

索引表可应用在以下情况:

·        联机事务处理(OLTP)

·        Internet (例如:搜索引擎和门户网络)

·        电子商务 (例如:电子商店和购物目录)

·        数据仓库

·        分析应用

 

<think>首先,用户的问题是:“我想了解表索引的增加和删除相关内容 请问表索引的增加和删除操作”。用户提到了站内引用,所以我需要参考这些引用。 回顾引用内容: - 引用[1]:提供了创建索引的SQL语句,包括创建单一索引和复合索引的语法。 - 引用[2]:提到MySQL支持的存储引擎,以及CREATE TABLE, DROP TABLE, ALTER TABLE, CREATE INDEX, DROP INDEX语句。 - 引用[3]:讨论Elasticsearch中的索引和映射,但用户的问题是关于数据库表索引,所以可能不直接用。 - 引用[4]:关于Oracle删除表时索引也会删除,以及索引状态检查。 - 引用[5]:解释表的定义,强调索引依附于表。 用户的问题集中在表索引的增加和删除操作,所以我应该基于这些引用构建回答。重点是创建和删除索引的SQL操作。 系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 用户可见层指令: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 结构化回答: 1. **逐步解释索引的增加和删除操作**:先定义索引是什么,然后创建索引的语法,再删除索引的语法。 2. **参考引用**:在适当的地方添加引用标识。 3. **使用中文**。 4. **生成相关问题**:在最后添加相关问题部分。 索引增加操作: - 创建索引可以使用CREATE INDEX语句。 - 从引用[1],有语法:`create index 索引名 on 表名 (字段名)` - 从引用[2],同样提到CREATE INDEX语句。 索引删除操作: - 删除索引可以使用DROP INDEX语句。 - 引用[2]提到DROP INDEX语句。 - 引用[4]提到删除表时索引也会被删除,但用户问的是删除索引操作本身。 其他要点: - 索引的类型:单一索引、复合索引(引用[1])。 - 索引的存储和优化考虑。 - 不同数据库可能有差异,但用户引用涉及MySQL和Oracle,所以我应该说明通用语法或差异。 回答结构: 1. **简介**:解释索引的作用(基于引用[5])。 2. **增加索引**:详细说明CREATE INDEX语句,包括语法、示例。 3. **删除索引**:详细说明DROP INDEX语句,包括语法、示例。 4. **注意事项**:如删除表时索引也被删除(引用[4]),索引管理的最佳实践。 5. **相关问题**:生成相关问题。 确保LaTeX正确:用户的问题涉及SQL代码,不涉及数学公式,所以可能不需要数学表达式,但如果提到任何数学概念(如索引大小计算),则使用LaTeX。否则,主要用代码块。 在回答中,SQL代码应该用代码块格式,如系统示例中的Python代码。 最终生成相关问题: - 例如:如何选择索引字段?索引对性能的影响?等等。 完整回答: - 使用标题或分段。 - 自然地添加引用。 </think>### 表索引的增加和删除操作详解 表索引是数据库优化的重要手段,能显著提升查询效率。索引本质上是数据的逻辑结构,依附于表(如表是存储数据的核心对象[^5]),通过快速定位数据减少全表扫描。下面我将逐步解释索引的增加(创建)和删除操作,基于通用SQL语法(如MySQL、Oracle等),并结合您的引用内容。不同数据库系统(如MySQL、Oracle)语法相似,但细节可能略有差异,我会注明关键点。 #### 1. **索引的增加操作(创建索引)** 创建索引使用`CREATE INDEX`语句。索引可以是单一索引(基于单个字段)或复合索引(基于多个字段),目的是加速查询性能。创建索引时需考虑存储参数(如初始大小、增长空间),以避免资源浪费[^1][^2]。 **通用语法:** ```sql -- 创建单一索引(基于单个字段) CREATE INDEX 索引名 ON 表名 (字段名) TABLESPACE 数据库名 -- 指定存储位置(可选) PCTFREE 10 -- 预留空间百分比(Oracle特有) INITRANS 2 -- 初始事务槽数(Oracle特有) MAXTRANS 255 -- 最大事务槽数(Oracle特有) STORAGE ( INITIAL 64K -- 初始分配空间 NEXT 1M -- 下次扩展空间 MINEXTENTS 1 -- 最少扩展区数 MAXEXTENTS UNLIMITED -- 最多扩展区数 ) NOLOGGING; -- 不记录日志(可选,加速创建) -- 创建复合索引(基于多个字段) CREATE INDEX 索引名 ON 表名 (字段名1, 字段名2) TABLESPACE 数据库名 ... (其他参数同上); ``` **示例说明:** - **单一索引示例**:在`employees`表的`last_name`字段上创建索引。 ```sql CREATE INDEX idx_lastname ON employees (last_name) TABLESPACE users STORAGE (INITIAL 64K, NEXT 1M); ``` - **复合索引示例**:在`orders`表的`customer_id`和`order_date`字段上创建索引,以提高多条件查询速度[^1]。 ```sql CREATE INDEX idx_customer_order ON orders (customer_id, order_date); ``` **关键注意事项:** - **存储引擎影响**:MySQL中索引行为取决于存储引擎(如InnoDB支持事务安全),创建索引前需确认表结构[^2]。 - **性能考虑**:索引会增加写入开销(如INSERT/UPDATE变慢),建议在低峰期创建。Oracle的参数如`PCTFREE`可优化空间利用率[^1]。 - **适用场景**:常见于WHERE、JOIN或ORDER BY频繁使用的字段[^5]。 #### 2. **索引的删除操作(删除索引)** 删除索引使用`DROP INDEX`语句,通常在索引不再需要或影响性能时执行。删除索引不会删除表数据,但会移除索引结构。注意,删除表会自动删除其所有索引[^4],这是数据库的级联行为。 **通用语法:** ```sql DROP INDEX 索引名 ON 表名; -- MySQL语法 -- 或 DROP INDEX 索引名; -- Oracle语法(需指定表名上下文) ``` **示例说明:** - **MySQL示例**:删除`employees`表上的`idx_lastname`索引。 ```sql DROP INDEX idx_lastname ON employees; ``` - **Oracle示例**:删除`orders`表上的`idx_customer_order`索引,并检查状态确认。 ```sql DROP INDEX idx_customer_order; -- 检查索引状态(引用[4]示例) SELECT index_name, status FROM user_indexes WHERE table_name = 'ORDERS'; ``` 执行后,索引状态变为`UNUSABLE`或从系统视图中消失[^4]。 **关键注意事项:** - **删除影响**:删除索引可能暂时降低查询速度,但释放了存储空间。在Oracle中,删除分区或表时会自动级联删除索引[^4]。 - **状态检查**:操作后建议查询索引状态(如Oracle的`user_indexes`视图),避免残留无效索引[^4]。 - **最佳实践**:删除前备份索引定义,必要时重建索引(如数据变更后)。 #### 3. **操作注意事项与最佳实践** - **索引管理**:创建和删除索引都是DDL操作,可能锁定表(阻塞查询),建议在维护窗口执行。例如,MySQL的`CREATE INDEX`语句会锁定表写入[^2]。 - **兼容性问题**:MySQL和Oracle语法类似,但Oracle更强调存储参数(如`TABLESPACE`),而MySQL更简化。Elasticsearch等NoSQL系统则有不同映射机制[^3]。 - **性能优化**:索引不是越多越好——复合索引优先于多个单一索引,定期分析索引使用率(如MySQL的`EXPLAIN`命令)。索引占用空间的计算公式可表示为:$ \text{索引大小} \propto \text{记录数} \times \text{字段长度} $。 - **风险提示**:误删索引可能导致查询性能下降;删除表时会自动删除索引(引用[4]),因此操作需谨慎。 通过以上步骤,您可以安全地管理索引。如果需要数据库特定示例(如MySQL或Oracle),请提供更多细节,我会进一步补充。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值