Oracle数据访问和索引的使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle数据访问和索引的使用相关的知识,希望对你有一定的参考价值。

参考技术A

· 通过全表扫描的方式访问数据;

· 通过ROWID访问数据;

· 通过索引的方式访问数据;

· Oracle顺序读取表中所有的行,并逐条匹配WHERE限定条件。

· 采用多块读的方式进行全表扫描,可以有效提高系统的吞吐量,降低I/O次数。

· 即使创建索引,Oracle也会根据CBO的计算结果,决定是否使用索引。

注意事项:

· 只有全表扫描时才可以使用多块读。该方式下,单个数据块仅访问一次。

· 对于数据量较大的表,不建议使用全表扫描进行访问。

· 当访问表中的数据量超过数据总量的5%—10%时,通常Oracle会采用全表扫描的方式进行访问。

· 并行查询可能会导致优化器选择全表扫描的方式。1.2ROWID访问表

· Rowid是数据存放在数据库中的物理地址,能够唯一标识表中的一条数据。

· Rowid指出了一条记录所在的数据文件、块号以及行号的位置,因此通过ROWID定位单行数据是最快的方法。

注意事项:

· Rowid作为一个伪列,其数值并不存储在数据库中,当查询时才进行计算。

· Rowid除了在同一集簇中可能不唯一外,每条记录的Rowid唯一。1.3 INDEX访问表

· 通过索引查找相应数据行的Rowid,再根据Rowid查找表中实际数据的方式称为“索引查找”或者“索引扫描”。

· 一个Rowid对应一条数据行(根据Rowid查找结果,仅需要对Rowid相应数据的数据块进行一次I/O操作),因此该方式属于“单块读”。

· 对于索引,除了存储索引的数据外,还保存有该数据对应的Rowid信息。

· 索引扫描分为两步:1)扫描索引确定相应的Rowid信息。 2)根据Rowid从表中获得对应的数据。

注意事项:

· 对于选择性高的数据行,索引的使用会提升查询的性能。但对于DML操作,尤其是批量数据的操作,可能会导致性能的降低。

· 全表扫描的效率不一定比索引扫描差,关键看数据在数据块上的具体分布。

索引是关系数据库中用于存放每一条记录的一种对象,主要目的是加快数据的读取速度和完整性检查。建立索引是一项技术性要求高的工作。一般在数据库设计阶段的与数据库结构一道考虑。应用系统的性能直接与索引的合理直接有关。

(1) 单列索引

单列索引是基于单个列所建立的索引。

(2) 复合索引

复合索引是基于两列或是多列的索引,在同一张表上可以有多个索引,但是要求列的组合必须不同。

(1) 重命名索引

(2) 合并索引

(表使用一段时间后在索引中会产生碎片,此时索引效率会降低,可以选择重建索引或者合并索引,合并索引方式更好些,无需额外存储空间,代价较低)

(3) 重建索引

方式一:删除原来的索引,重新建立索引

当不需要时可以将索引删除以释放出硬盘空间。命令如下:

例如:

注:当表结构被删除时,有其相关的所有索引也随之被删除。

方式二: Alter index 索引名称 rebuild;

· 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

· 索引可以大大加快数据的检索速度,这是创建索引的最主要的原因。

· 可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

· 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

· 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

· 索引的层次不要超过4层。

· 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

· 除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

· 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

· 更新数据的时候,系统必须要有额外的时间来同时对索引进行更新,以维持数据和索引的一致性。

1) 不恰当的索引不但于事无补,反而会降低系统性能。因为大量的索引在进行插入、修改和删除操作时比没有索引花费更多的系统时间。

1) 应该建索引的列

· 在经常需要搜索的列上,可以加快搜索的速度;

· 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;

· 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;

· 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;

· 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;

· 在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

2) 不应该建索引的列

· 在大表上建立索引才有意义,小表无意义。

· 对于那些在查询中很少使用或者参考的列不应该创建索引。

· 对于那些只有很少数据值的列也不应该增加索引。比如性别,在查询的结果中,结果集的数据行占了表中数据行的很大比例,。增加索引,并不能明显加快检索速度。

· 对于那些定义为blob数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。

· 当修改性能远远大于检索性能时,不应该创建索引。

一个表中有几百万条数据,对某个字段加了索引,但是查询时性能并没有什么提高,这主要可能是oracle的索引限制造成的。Oracle的索引有一些索引限制,在这些索引限制发生的情况下,即使已经加了索引,oracle还是会执行一次全表扫描,查询的性能不会比不加索引有所提高,反而可能由于数据库维护索引的系统开销造成性能更差。

下面的查询即使在djlx列有索引,查询语句仍然执行一次全表扫描。

把上面的语句改成如下的查询语句,这样,在采用基于规则的优化器而不是基于代价的优化器(更智能)时,将会使用索引。

特别注意:通过把不等于操作符改成OR条件,就可以使用索引,避免全表扫描。

使用IS NULL或IS NOT NULL同样会限制索引的使用。因此在建表时,把需要索引的列设成NOT NULL。如果被索引的列在某些行中存在NULL值,就不会使用这个索引(除非索引是一个位图索引)。

如果不使用基于函数的索引,那么在SQL语句的WHERE子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。 下面的查询不会使用索引(只要它不是基于函数的索引)

也是比较难于发现的性能问题之一。比如:bdcs_qlr_xz中的zjh是NVARCHAR2类型,在zjh字段上有索引。如果使用下面的语句将执行全表扫描。

因为Oracle会自动把查询语句改为

特别注意:不匹配的数据类型之间比较会让Oracle自动限制索引的使用,即便对这个查询执行Explain Plan也不能让您明白为什么做了一次“全表扫描”。

(1) 索引无效

(2) 索引有效

什么时候应该使用 Oracle 的索引组织表?或者,我什么时候不应该?

【中文标题】什么时候应该使用 Oracle 的索引组织表?或者,我什么时候不应该?【英文标题】:When should I use Oracle's Index Organized Table? Or, when shouldn't I? 【发布时间】:2011-03-23 21:56:37 【问题描述】:

索引组织表 (IOT) 是存储在索引结构中的表。而存储的表 在堆中是无组织的,IOT中的数据是按主键存储和排序的(数据是索引)。 IOT 的行为就像“常规”表一样,您使用相同的 SQL 来访问它们。

适当的关系数据库中的每个表都应该有一个主键...如果我的数据库中的每个表都有一个主键,我应该总是使用索引组织的表吗?

我猜答案是否定的,那么索引组织表何时不是最佳选择?

【问题讨论】:

【参考方案1】:

基本上,索引组织表是没有表的索引。我们可以在 USER_TABLES 中找到一个表对象,但它只是对基础索引的引用。索引结构与表的投影相匹配。因此,如果您有一个表,其列由主键和最多一个其他列组成,那么您就有可能是 INDEX ORGANIZED 的候选者。

索引组织表的主要用例是一个几乎总是通过其主键访问的表,我们总是希望检索它的所有列。在实践中,索引组织的表最有可能是引用数据、代码查找事务。应用程序表几乎总是堆组织的。

该语法允许 IOT 有多个非键列。有时这是正确的。但这也表明我们可能需要重新考虑我们的设计决策。当然,如果我们发现自己正在考虑在非主键列上需要额外的索引,那么使用常规堆表可能会更好。因此,由于大多数表可能需要额外的索引,因此大多数表不适合 IOT。


回到这个答案,我看到这个线程中的其他几个回复建议交叉表作为物联网的合适候选者。这似乎是合理的,因为交集表通常有一个与候选键匹配的投影:STUDENTS_CLASSES 的投影可能只有 (STUDENT_ID, CLASS_ID)。

我不认为这是铸铁。交集表通常有一个技术键(即 STUDENT_CLASS_ID)。它们也可能有非键列(START_DATE、END_DATE 等元数据列很常见)。也没有普遍的访问路径——我们想找到所有上课的学生,就像我们想找到一个学生正在上的所有课程一样——所以我们需要一个同样支持这两者的索引策略。并不是说交集表不是物联网的用例。只是它们不会自动如此。

【讨论】:

【参考方案2】:

我会考虑将它们用于非常窄的表(例如用于解析多对多表的连接表)。如果(实际上)表中的所有列都将在索引中,那么为什么不使用 IOT。

正如 Richard Foote here 所讨论的,小桌子可以成为 IOT 的良好候选者@

【讨论】:

【参考方案3】:

我认为以下类型的表格非常适合 IOT:

“小”“查找”类型的表(例如,经常查询、不经常更新、适合相对较少的块) 您已经拥有一个涵盖所有列的索引的任何表(即,如果索引与 100% 的数据重复,也可以节省表使用的空间)

【讨论】:

对不起,这几乎与 Gary 的答案重复。【参考方案4】:

来自 Oracle Concepts 指南:

索引组织的表在以下情况下很有用 必须存储相关的数据 在一起或数据必须物理上 以特定顺序存储。这个类型 of table 常用于信息 检索,空间(参见“概述 Oracle Spatial”)和 OLAP 应用程序(参见“OLAP”)。

这个来自 AskTom 的 question 也可能会引起一些兴趣,尤其是当有人给出一个场景然后询问 IOT 是否比堆组织表执行得更好时,Tom 的回答是:

我们可以整天假设,但是 除非你测量它,否则你永远不会 肯定知道。

【讨论】:

我一直觉得“存储在一起”的东西是一个红鲱鱼,因为表的主键可能没有意义。您可能希望对同时插入的记录进行聚类,但行的共同定位通常是多行具有相同(例如)customer_id 或 invoice_id 的问题,在这种情况下,散列聚类是更好的选择。 【参考方案5】:

如果您只通过键、整个键以及仅通过键访问该表中的数据,那么索引组织表通常是一个不错的选择。

此外,对于索引组织表可以使用和不能使用哪些其他数据库功能存在许多限制——我记得至少在一个版本中,不能将逻辑备用数据库与索引组织表一起使用。如果索引组织表妨碍您使用其他功能,则它不是一个好的选择。

【讨论】:

【参考方案6】:

IOT 真正节省的只是表段上的逻辑读取,因为您可能在 IOT/索引上花费了两三个或更多,这并不总是一个很好的节省,除了小数据集。

另一个加快查找速度(尤其是在较大的表上)的特性是单表哈希集群。正确创建后,它们对于大型数据集比 IOT 更有效,因为它们只需要一次逻辑读取即可找到数据,而 IOT 仍然是需要多个逻辑 i/o 来定位叶节点的索引。

【讨论】:

【参考方案7】:

我本身无法对 IOT 发表评论,但是如果我没看错,那么它们与 SQL Server 中的“聚集索引”相同。通常,如果您的主键(或者如果它不是主键,则您要索引的值)可能相当随机地分布,您应该考虑不使用这样的索引 - 因为这些插入可能会导致许多页面拆分(贵)。

诸如标识列(Oracle 中的序列?)之类的索引和“当前日期前后”的日期往往是此类索引的良好候选者。

【讨论】:

你是对的——在 Oracle 中,索引只是被称为索引,没有你在 MySQL 和 SQL Server 中看到的区别。 Oracle 中的未索引表是堆排序的。序列更接近 SQL Server 的 IDENTITY 列,因为序列中的增量和偏移值彼此独立 - 与 MySQL 不同。但序列也不附加到任何一张桌子上——它们是独立的对象。这也意味着您可以在一个表中使用多个序列(尽管不常见)。【参考方案8】:

索引组织表(与普通表不同)有自己的结构化、存储和索引数据方式。

索引组织表 (IOT) 是实际保存正在被索引的数据的索引,与存储在其他地方并链接到实际数据的索引不同。

【讨论】:

这是对 IOT 概念的解释,但实际上并没有通过解释何时使用一个而不是标准表来解决问题。

以上是关于Oracle数据访问和索引的使用的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 11g R2 索引

oracle 位图索引

oracle中的视图序列索引

oracle视图和索引

了解oracle数据库数据访问机制

执行计划-数据访问方式(全表扫描与4种索引的方式)