数据库使用-oracle索引的创建和分类

数据库使用-oracle索引的创建和分类

索引是数据库中一种可选的数据结构,她通常与表或簇相关。用户可以在表的一列或数列上建立索引,以提高在此表上执行 SQL
语句的性能。就像本文档的索引可以帮助读者快速定位所需信息一样,Oracle
的索引提供了更为迅速地访问表数据的方式。正确地使用索引能够显著的减少磁盘 I/O。

Oracle 提供了多种类型的索引,可以互为补充地提升查询性能:

·        平衡树索引(B-tree index)

·        平衡树簇索引(B-tree cluster index)

·        哈希簇索引(hash cluster index)

·        反向键索引(reverse key indexes)

·        位图索引(bitmap index)

·        位图连接索引(bitmap join index)

·        函数索引(function-based index)

无论索引是否存在都无需对已有的 SQL
语句进行修改。索引只是提供了一种快速访问数据的路径,因此她只会影响查询的执行速度,但是数据在编辑的过程中,会不断去创建或者更新索引,会让整个系统的磁盘开销非常大,进一步会影响整个系统的运行

因此,当我们要创建索引的时候,一定要问自己,这个索引真的有必要创建么?

索引在逻辑上和物理上都与其基表(base table)是相互独立的。用户可以随时创建(create)或移除(drop)一个索引,而不会影响其基表或基表上的其他索引。当用户移除一个索引时,所有的应用程序仍然能够继续工作,但是数据访问速度有可能会降低。作为一种独立的数据结构,索引需要占用存储空间。

当索引被创建后,对其的维护与使用都是 Oracle
自动完成的。当索引所依赖的数据发生插入,更新,删除等操作时,Oracle
会自动地将这些数据变化反映到相关的索引中,无需用户的额外操作。

即便索引的基表中插入新的数据,对被索引数据的查询性能基本上能够保持稳定不变。但是,如果在一个表上建立了过多的索引,将降低其插入,更新,及删除的性能。因为 Oracle
必须同时修改与此表相关的索引信息。

优化器可以使用已有的索引来建立(build)新的索引。这将加快新索引的建立速度。

唯一索引和非唯一索引

索引(index)可以是唯一(unique)的或非唯一(nonunique)的。在一个表上建立唯一索引(unique
index)能够保证此表的索引列(一列或多列)不存在重复值。而非唯一索引(nonunique index)并不对索引列值进行这样的限制。

Oracle 建议使用 CREATE UNIQUEINDEX 语句显式地创建唯一索引(unique index)。通过主键(primary
key)或唯一约束(unique constraint)来创建唯一索引不能保证创建新的索引,而且用这些方式创建的索引不能保证为唯一索引。

复合索引

复合索引(composite index)(也被称为连结索引(concatenated index))是指创建在一个表的多列上的索引。复合索引内的列可以任意排列,她们在数据表中也无需相邻。

如果一个 SELECT
语句的 WHERE
子句中引用了复合索引(composite index)的全部列(all of the column)或自首列开始且连续的部分列(leading
portion of thecolumn),将有助于提高此查询的性能。因此,索引定义中列的顺序是很重要的。大体上说,经常访问的列(most commonly accessed)或选择性较大的列(most
selective)应该放在前面。

一个常规的(regular)复合索引(composite index)不能超过
32 列,而位图索引(bitmap index)不能超过 30
列。索引中一个键值(key value)的总长度大致上不应超过一个数据块(data block)总可用空间的一半。

索引和键

索引(index)与键(key)是不同的概念,但是这两个术语经常被混用。索引是在数据库中实际存储的数据结构,用户可以使用
SQL 语句对其进行创建(create),修改(alter),或移除(drop)。索引提供了一种快速访问表数据的途径。而键只是一个逻辑概念。键的概念主要在
Oracle 的完整性约束(integrity constraint)功能中使用,完整性约束用于保证数据库中的业务规则(business rule)。

因为 Oracle
也会使用索引(index)来实现某些完整性约束(integrity constraint),因此索引与键(key)这两个术语经常被混用。注意不要将二者混淆。

索引和空值

对于一个数据表的两行或多行,如果其索引列(key column)中全部非空(non-NULL)的值完全相同(identical),那么在索引中这些行将被认为是相同的;反之,在索引中这些行将被认为是不同的。因此使用 UNIQUE 索引可以避免将包含
NULL 的行视为相同的。以上讨论并不包括索引列的列值(column value)全部为 NULL 的情况。

Oracle 不会将索引列(key column)全部为 NULL 的数据行加入到索引中。不过位图索引(bitmap
index)是个例外,簇键(cluster key)的列值(column value)全部为 NULL 时也是例外。

函数索引

如果一个函数(function)或表达式(expression)使用了一个表的一列或多列,则用户可以依据这些函数或表达式为表建立索引,这样的索引被称为函数索引(Function-Based
Index)。函数索引能够计算出函数或表达式的值,并将其保存在索引中。用户创建的函数索引既可以是平衡树类型(B-tree index)的,也可以是位图类型(bitmap index)的。

用于创建索引的函数可以是一个数学表达式(arithmetic expression),也可以是使用了
PL/SQL 函数(PL/SQL function),包函数(package function),C
外部调用(C callout),或 SQL
函数(SQL function)的表达式。用于创建索引的函数不能包含任何聚合函数(ggregate function),如果为用户自定义函数,则在声明中必须使用 DETERMINISTIC关键字。如果在一个使用对象类型(object
type)的列上建立函数索引,则可以使用此对象的方法(method)作为函数,例如此对象的 map
方法。用户不能在数据类型为 LOB,REF,或嵌套表(nested
table)的列上建立函数索引,也不能在包含 LOB,REF,或嵌套表等数据类型的对象类型列上建立函数索引。

使用函数索引

如果一个 SQL
语句的 WHERE
子句中使用了函数,那么建立相应的函数索引(function-based index)是提高数据访问性能的有效机制。表达式(expression)的结果经过计算后将被存储在索引中。但是当执行 INSERT 和 UPDATE 语句时,Oracle
需要进行函数运算以便维护索引。

例如,如果用户创建了以下函数索引:

CREATE INDEX idx ON table_1 (a + b * (c – 1),a, b);

当 Oracle
处理如下查询时就可以使用之前建立的索引:

SELECT a FROM table_1 WHERE a + b * (c – 1)< 100;

使用 UPPER(column_name) 或 LOWER(column_name) 函数建立函数索引(function-based
index)有助于与大小写无关(case-insensitive)的查询。例如创建以下函数索引:

CREATE INDEX uppercase_idx ON employees (UPPER(first_name));

有助于提高以下查询的性能:

SELECT * FROM employees WHEREUPPER(first_name) = ‘RICHARD’;

函数索引的优化

用户必须为优化器(optimizer)收集关于函数索引(unction-based
index)的统计信息(statistic)。否则处理 SQL
语句时将不会使用此索引。

当一个查询的 WHERE
子句中含有表达式(expression)时,优化器可以对函数索引(function-based index)进行索引区间扫描(index
range scan)。例如以下查询:

SELECT * FROM t WHERE a + b < 10;

如果使用表达式(expression) a+b 建立的索引,优化器(optimizer)就能够进行索引区间扫描(index
range scan)。如果谓词(predicate,即 WHERE 子句)产生的选择性(selectivity)较低,则对区间扫描极为有利。此外,如果表达式的结果物化在函数索引内(function-based
index),优化器将能更准确地估计使用此表达式的谓词的选择性。

优化器(optimizer)能够将 SQL
语句及函数索引(function-based index)中的表达式解析为表达式树(expression tree)并进行比较,从而实现表达式匹配。这个比较过程是大小写无关的(case-insensitive),并将忽略所有空格(blank
space)。

逆序键索引

用户可以创建逆序键索引(reverse key index),此处的逆序指索引列值(index
key value)得各个字节(byte)按倒序排列,而非索引列(index key)逆序排列。在
RAC 环境中,使用这样的排列方式可以避免由于对索引的修改集中在一小部分叶块(leaf block)上而造成的性能下降。通过使索引的键值逆序排列,可以使插入操作分布在索引的全部叶块中。

使用逆序键索引(reverse key index)后将无法对此索引进行索引区间扫描(index
range scanning),因为在逆序键索引中,词汇上(lexically)相邻的索引键(index
key)在存储上未必相邻。因此在逆序键索引上只能进行确定键扫描(fetch-by-key scan)或全索引扫描(full-index
scan)。

有些情况下,使用逆序键索引(reverse key index)可以令
RAC 环境下的 OLTP
应用效率更高。例如,为一个 e-mail
应用中的所有邮件进行索引:由于用户可能保存旧的邮件,因此索引必须做到既能快速访问最新邮件,也能快速访问旧邮件。

用户使用 REVERSE 就可以轻易地创建逆序键索引(reverse
key index)。在 CREATE INDEX语句中使用 REVERSE 关键字作为创建索引的选项:

CREATE INDEX i ON t (a,b,c) REVERSE;

用户也可以在 REBUILD 子句后添加 NOREVERSE 关键字将一个逆序键索引(reverse
key index)转换为常规的索引:

ALTER INDEX i REBUILD NOREVERSE;

如果 REBUILD 子句后没有使用 NOREVERSE 关键字,那么逆序键索引(reverse
key index)被重建后仍将保持逆序。

位图索引

位图索引也只一种非常重要的索引,在一些特定的环境中,有非常好的效果,但是非常容易被滥用,使用前后需要仔细验证看是否达到预期效果。

表分析

有的时候,我们会发现虽然有索引,但是执行计划不走索引,全表扫描跑的哗哗的,这个时候要查看下这个表的最后的分析时间,如果DBA没有及时做表分析,那么索引可能用不到。

select * from user_tables t ;

找到对应的表的last_analyzed时间;如果时间太老或者没有时间,那么说明这张表需要做表分析了。

表分析一般要在业务性能不太繁忙的时候做,先了解一下什么是表分析:

简单的说,就是收集表和索引的信息,CBO根据这些信息决定SQL最佳的执行路径。通过对表的分析,可以产生一些统计信息,通过这些信息oracle的优化程序可以优化。

oracle的联机文档描述了analyze的做用:

Use the ANALYZE statement to collect non-optimizer statistics, forexample, to:

--使用analyze功能可以收集一些没有进行优化的统计信息,例如:

Collect or delete statistics about an index or index partition, table ortable partition,

--聚集或删除索引或索引分区,表或表分区

index-organized table, cluster, or scalar object attribute.

--索引表,串,或游标的目标属性等统计信息

Validate the structure of an index or index partition, table or tablepartition, index-organized table,

--增加下列结构的有效性:索引或索引分区,表或表分区,索引表

cluster, or object reference (REF).

--串,目标参照

Identify migrated and chained rows of a table or cluster.

--鉴别一个表或串中已经被移动的抑或被锁住的列。

表分析的语句参考:

analyze table tableName compute statistics;

平衡树结构的优势

平衡树数据结构(B-tree structure)具有以下优势:

·        平衡树(B-tree)内所有叶块(leaf block)的深度相同,因此获取索引内任何位置的数据所需的时间大致相同。

·        平衡树索引(B-tree index)能够自动保持平。

·        平衡树内的所有块容量平均在总容量的 3/4
左右。

·        在大区间(wide range)范围内进行查询时,无论匹配个别值(exact match)还是搜索一个区间(range
search),平衡树都能提供较好的查询性能。

·        数据插入(insert),更新(update),及删除(delete)的效率较高,且易于维护键值的顺序(key
order)

·        大型表,小型表利用平衡树进行搜索的效率都较好,且搜索效率不会因数据增长而降低。

索引唯一扫描

索引唯一扫描(index unique scan)是效率最高的数据访问方式之一。从平衡树索引(B-tree
index)中获取数据时将采用此种方式。当一个唯一索引(采用平衡树结构)的全部列都包含在查询条件中,且查询体条件表达式均为等号(equality)时,优化器将选择使用索引唯一扫描。

索引区间扫描

当访问选择性较大的数据(selective data)时 Oracle
常进行索引区间扫描(index range scan)。扫描区间可以是封闭的(bounded)(两端均封闭),也可以是不封闭的(unbounded)(一端或两端均不封闭)。扫描所返回的数据按照索引列的升序进行排列,对于索引值相同的行将按 ROWID 的升序排列。

性能上及存储上的考虑

键压缩(key compression)能够节约大量存储空间,因此用户可以在一个索引块(index
block)内存储更多的索引键(index key),从而减少 I/O,提高性能。

键压缩(key compression)能够减少索引所需的存储空间,但索引扫描时需要重构(reconstruct)键值(key
value),因此增加了 CPU
的负担。此外键压缩也会带来一些存储开销,每个前缀(prefix entry)需要 4
字节(byte)的管理开销。

使用键压缩

键压缩(key compression)在多种情况下都能够发挥作用,例如:

·        对于非唯一索引(nonunique index),Oracle
会在每个重复的索引键(index key)之后添加 rowid
以便区分。如果使用了键压缩,在一个索引块(index block)内,Oracle
只需将重复的索引键作为前缀((prefix entry))存储一次,并用各行的 rowid
作为后缀(suffix entry)。

·        唯一索引(nonunique index)中也存在相同的情况。例如唯一索引(stock_ticker,transaction_time)的含义是(项目,时间戳),通常数千条记录中stock_ticker 的值是相同的,但她们对应的 transaction_time 值各不相同。使用了键压缩后,一个索引块中每个 stock_ticker 值作为前缀只需存储一次,而各个transaction_time 值则作为后缀存储,并引用一个共享的 stock_ticker 前缀。

·        在一个包含 VARRAY 或 NESTED TABLE 数据类型(datatype)的索引表(index-organized
table)中,这些collection
类型中各个元素(element)的对象标识符(object identifier)是重复的。用户可以使用键压缩以避免重复存储这些对象标识符。

有些情况无法使用键压缩(key compression)。例如,一个只有一个索引键(index
key)的唯一索引(unique index)就无法使用键压缩,因为索引键中不存在可供共享的分组片段(grouping piece)。

时间: 2024-10-23 14:38:19

数据库使用-oracle索引的创建和分类的相关文章

让你提前认识软件开发(27):数据库表及索引的创建

第2部分 数据库SQL语言 数据库表及索引的创建         数据表(或称表),是数据库最重要的组成部分之一.数据库只是一个框架,数据表才是其实质的内容.举个例子来说,数据库就像是一座空旷的房子,而数据表是里面的家具,没有家具的房子只是一个空壳而已.根据信息的分类情况,一个数据库中可能包含若干个不同用途的数据表. 表结构有简单.有复杂,这就对开发人员提出了要求.如何设计一个表的字段才是最好的?表的字段如何命名?如何定义表字段的类型?如何建立索引?等等. 1. 修改之前的建表脚本 在作者从事过

让你提前知道软件开发(27):创建数据库表和索引

文章2部分 数据库SQL语言 数据库表及索引的创建         数据表(或称表),是数据库最重要的组成部分之中的一个.数据库仅仅是一个框架.数据表才是事实上质的内容.举个样例来说,数据库就像是一座空旷的房子.而数据表是里面的家具,没有家具的房子仅仅是一个空壳而已.依据信息的分类情况,一个数据库中可能包括若干个不同用途的数据表. 表结构有简单.有复杂,这就对开发者提出了要求. 怎样设计一个表的字段才是最好的?表的字段怎样命名?怎样定义表字段的类型?怎样建立索引?等等. 1. 改动之前的建表脚本

oracle 索引失效原因

摘自网络http://blog.chinaunix.net/uid-23622436-id-3184356.html oracle 索引失效的原因 分类: Oracle 1) 没有查询条件,或者查询条件没有建立索引 2) 在查询条件上没有使用引导列 3) 查询的数量是大表的大部分,应该是30%以上. 4) 索引本身失效 5) 查询条件使用函数在索引列上(见12) 6) 对小表查询 7) 提示不使用索引 8) 统计数据不真实 9) CBO计算走索引花费过大的情况.其实也包含了上面的情况,这里指的是

Oracle数据库管理之创建和删除数据库

一.数据库管理概述 在完成Oracle软件安装后,DBA就应该对组织和管理数据库负责任,其主要任务是: (1)启动和关闭数据库: (2)创建数据库: (3)删除数据库: (4)调整初始化参数: (5)管理网络. 对于数据库的管理,必须要具有SYSDBA和SYSOPER的角色,才有权启动.关闭.运行数据库.SYSDBA角色拥有SYS数据表的所有权限,SYSOPER的角色拥有Public数据表的所有权限. 二.数据库的管理方法 (1)DOS命令行方式 命令行管理是DBA管理数据库服务器的传统方法.在

Oracle 10g通过创建物化视图实现不同数据库间表级别的数据同步

摘自:http://blog.csdn.net/javaee_sunny/article/details/53439980 目录(?)[-] Oracle 10g 物化视图语法如下 实例演示 主要步骤 在A节点创建原表和物化视图日志 在B节点创建连接A节点的远程链接 在B节点处创建目标表和与目标表名称相同的物化视图 在B节点处刷新物化视图 升级采用存储过程定时任务JOB方式定时刷新物化视图 进一步优化 文章更新记录 参考文章 Oracle 10g 物化视图语法如下: create materia

1.安装oracle软件及创建数据库

一.硬件资源 内存:1G以上 SWAP空间:至少1.5G,要求为内存的2倍 temp空间:400M linux的临时空间是/tmp windows的临时空间如下: c:\> echo %homedrive%%homepath%\local settings\temp 硬盘空间:linux/unix需要1.3~3.5G windows需要1~1.5G 二.OFA最佳灵活体系结构(目录命名) 1.linux/unix下面对于mount点的命名采用/pm的方式 p:字符常量,通常是u m:固定长度,通

Oracle如何实现创建数据库、备份数据库及数据导出导入的一条龙操作

Oracle如何实现创建数据库.备份数据库及数据导出导入的一条龙操作 Oracle中对数据对象和数据的管理,无疑都是使用PL/SQL Developer来进行管理,该工具也提供给我们很多方便.快捷的操作,使得我们不再为Oracle本身丑陋.难用的UI而抱怨.由于我们一般都是建建表.查查数据的操作居多,较少会考虑系统的整个Oracle的完整备份操作.但是在我们一些发布操作中,我们必须考虑如何把Oracle的对象.表数据导出到Sql脚本中,并且把创建Oracle表空间.创建Oracle数据库的操作也

[转] Oracle学习之创建数据库(新建实例)

由于项目需求,在本机中开发,需要新建oracle数据库实例,亲测可以. 出处:http://blog.csdn.NET/luiseradl/article/details/6972217 http://wenku.baidu.com/view/864b9b2c453610661ed9f469.html My points: (1)我的头头说一般不需要创建数据库,在Orcl数据库中创建用户,创建用户对应的表就成了: (2)删除数据库和创建数据库启动的软件是一个. 一.新建实例1.安装好Oracle

oracle 索引的(创建、简介、技巧、怎样查看)

一.索引简介1.索引相当于目录2.索引是通过一组排序后的索引键来取代默认的全表扫描检索方式,从而提高检索效率.3.索引的创建要适度,多了会影响增删改的效率,少了会影响查询的效率,索引最好创建在取值分散的列上,避免对同一张表创建过多的索引4.索引的使用对用户来说是透明的,由系统来决定什么时候使用索引.5.Oracle支持多种类型的索引,可以按列的多少.索引值是否唯一和索引数据的组织形式对索引进行分类,以满足各种表和查询条件的要求.(请见附件)a. 单列索引和复合索引    b.B树索引(creat