Oracle索引

15 篇文章 1 订阅
9 篇文章 0 订阅

索引的概念

索引是oracle的一个对象,是否使用索引由oracle决定,索引中存储了特定列的排序数据,实现对表的快速访问。

使用索引可以很快速查找到建立索引时列的值所在的行,而不必对表实现全表扫描,适当使用索引可以减少磁盘的I/O量。

索引的特点:

  1. 对于具有只读特性或较少插入、更新或删除操作的大表通常可以提高查询速度。
  2. 可以对表的一列或多列建立索引。
  3. 建立索引的数量没有限制。
  4. 索引需要磁盘储存,需要oracle自动维护。
  5. 索引对用户透明,是否使用索引是oracle决定的。

Oracle实现数据访问的方法

  1. 全表扫描
  2. 通过ROWID
  3. 使用索引
  • 全表扫描

SQL> explain plan for select*from dual;

已解释。

SQL> select * from table(dbms_xplan.display);  

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 272002086

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     2 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| DUAL |     1 |     2 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

已选择8行。
  • 通过行ID(略)

  • 使用索引

通过索引找到数据行的ROWID,然后通过ROWID直接到表中查找数据,这种方式成为索引查找或者索引扫描。

因为一个ROWID对应一个数据行,因此这种方式采用的也是单块读。

在索引中,除了存储每一个索引值,还会存储相应的ROWID,索引扫描分为两步:

  1. 扫描索引得到相应的ROWID。
  2. 通过找到ROWID从表中读取对应的数据。

通过执行计划判断索引的使用

SQL> explain plan for select * from scott.emp where empno=10;

已解释。

SQL>  select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2949544139

--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |    38 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    38 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------

   2 - access("EMPNO"=10)

已选择14行。

  索引扫描类型

根据索引类型、数据分布以及SQL等确定索引的扫描类型。

  1. 索引唯一扫描(INDEX UNIQUE SCAN)
  2. 索引范围扫描(INDEX RANGE SCAN)
  3. 索引全扫描(INDEX FULL SCAN)
  4. 索引快速扫描(INDEX FAST FULL SCAN)
  • 索引唯一扫描

索引唯一扫描通过指定UNIQUE键、主键,oracle通常返回一个数据行,因此采用的索引唯一扫描。

SQL> explain plan for select * from emp where empno=10;

已解释。

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2949544139

--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |    38 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    38 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------

   2 - access("EMPNO"=10)

已选择14行。
  • 索引范围扫描

如果发生如下情况时候需要使用使用索引范围扫描:

在unique键上使用range操作符(> , < , <> , >= , <= , between)

在组合索引上,只使用部分列进行查询,导致查询出多行

对非唯一索引列上进行查询

使用索引范围扫描

SQL> explain plan for select * from emp where empno>10;     

已解释。

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 169057108

--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |    14 |   532 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |    14 |   532 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | PK_EMP |    14 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------

   2 - access("EMPNO">10)

已选择14行。
  • 扫描全索引

当使用索引全扫描时,查询出的数据必须全部从索引中得到

SQL> explain plan for select * from emp;

已解释。

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |   532 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| EMP  |    14 |   532 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

已选择8行。
  • 索引快速扫描

索引快速扫描,扫描索引快中的所有数据块,与全扫描相类似,但是索引快速扫描不进行数据排序,在这种方式下,可以使用多块读功能、也可以使用并行读功能,最大化吞吐量。

使用索引快速扫描

SQL> explain plan for select empno,ename from emp;

已解释。

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |   140 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| EMP  |    14 |   140 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

已选择8行。

限制索引使用的情况

很多情况及时创建了索引,也会导致索引不能使用。

  • 使用不等于运算符

使用度等于运算符 < , > , != 在where中使用这些不等于条件,将会导致索引失败

SQL> explain plan for select * from emp where empno<>10;

已解释。

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |   532 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |    14 |   532 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

   1 - filter("EMPNO"<>10)

已选择13行。
  • 使用IS NULL 或者 IS NOT NULL

在where子句中使用IS NULL或者IS NOT NULL 同样会限制索引使用。

NULL判断影响索引使用(基于emp表SAL列创建B树索引)

SQL> select column_name from user_ind_columns where table_name='EMP';  

COLUMN_NAME
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMPNO

SQL> explain plan for select * from emp;

已解释。

SQL> select column_name from user_ind_columns where table_name='EMP';  

COLUMN_NAME
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMPNO

SQL> create index idx_sal_emp on emp(sal);

索引已创建。

SQL> select column_name from user_ind_columns where table_name='EMP';  

COLUMN_NAME
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SAL
EMPNO

不走索引走全表扫描

SQL> explain plan for select empno,ename,deptno from emp;

已解释。

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |   182 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| EMP  |    14 |   182 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

已选择8行。

建立索引

oracle建立索引使用CREATE INDEX来建立

对EMP表建立索引

SQL> create index emp_ename_idx on emp(ename);

索引已创建。

使用USER_INDEXES数据字典查询索引信息

从数据字典 USER_INDEXES可以详细地查看当前用户所拥有的索引信息,

SQL> select index_name,index_type,table_name,tablespace_name from user_indexes;

INDEX_NAME                                                                                 INDEX_TYPE
------------------------------------------------------------------------------------------ ---------------------------------------------------------------------------------
TABLE_NAME                                                                                 TABLESPACE_NAME
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
PK_EMP                                                                                     NORMAL
EMP                                                                                        USERS

IDX_SAL_EMP                                                                                NORMAL
EMP                                                                                        USERS

EMP_ENAME_IDX                                                                              NORMAL
EMP                                                                                        USERS


INDEX_NAME                                                                                 INDEX_TYPE
------------------------------------------------------------------------------------------ ---------------------------------------------------------------------------------
TABLE_NAME                                                                                 TABLESPACE_NAME
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
PK_DEPT                                                                                    NORMAL
DEPT                                                                                       USERS

创建索引表空间

SQL> create tablespace index_tbs
  2  datafile '/u01/app/oracle/oradata/tiqs/index_tbsl.dbf' size 100M autoextend on ;

表空间已创建。

创建多列索引

SQL> create index emp_name_sal_index on emp(ename,sal)
  2  tablespace index_tbs;

索引已创建。

查看多列索引


SQL> select index_name,table_name,tablespace_name from user_indexes where index_name like '%EMP%';

INDEX_NAME                                                                                 TABLE_NAME
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
TABLESPACE_NAME
------------------------------------------------------------------------------------------
PK_EMP                                                                                     EMP
USERS

IDX_SAL_EMP                                                                                EMP
USERS

EMP_ENAME_IDX                                                                              EMP
USERS


INDEX_NAME                                                                                 TABLE_NAME
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
TABLESPACE_NAME
------------------------------------------------------------------------------------------
EMP_NAME_SAL_INDEX                                                                         EMP
INDEX_TBS

查看索引

数据字典USER_IND_COLUMNS使得我们可以很方便查找一个索引所对应列的信息。

查询索引列相关的信息

SQL> select index_name,table_name,column_name from user_ind_columns;

INDEX_NAME                                                                                 TABLE_NAME
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
COLUMN_NAME
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMP_ENAME_IDX                                                                              EMP
ENAME

EMP_NAME_SAL_INDEX                                                                         EMP
SAL

EMP_NAME_SAL_INDEX                                                                         EMP
ENAME


INDEX_NAME                                                                                 TABLE_NAME
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
COLUMN_NAME
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IDX_SAL_EMP                                                                                EMP
SAL

PK_DEPT                                                                                    DEPT
DEPTNO

PK_EMP                                                                                     EMP
EMPNO


已选择6行。

重建索引

索引需要维护,不然如果建立了索引的表中有大量的删除和插入操作会使得索引很大,因为删除操作后,删除值所占用的索引空间不能够诶索引自动重新使用,而插入操作会不断使得索引变大

SQL> alter index emp_name_sal_index rebuild;

索引已更改。

SQL> alter index emp_name_sal_index rebuild tablespace tablespace_name;

索引已更改。

SQL> alter index emp_name_sal_index rebuild online;

索引已更改。

维护索引

维护索引就是修改索引的各种参数,在维护索引前首先需要指导当前索引的参数设置。

查询当前索引的参数设置

SQL> select index_name,pct_free,pct_increase,initial_extent,next_extent from  user_indexes;

INDEX_NAME                                                                                   PCT_FREE PCT_INCREASE INITIAL_EXTENT NEXT_EXTENT
------------------------------------------------------------------------------------------ ---------- ------------ -------------- -----------
PK_EMP                                                                                             10                       65536     1048576
IDX_SAL_EMP                                                                                        10                       65536     1048576
EMP_ENAME_IDX                                                                                      10                       65536     1048576
EMP_NAME_SAL_INDEX                                                                                 10                       65536     1048576
PK_DEPT                                                                                            10                       65536     1048576

通过rubuild修改索引参数

手动增加索引的磁盘空间

SQL> alter index EMP_ENAME_IDX allocate extent;

索引已更改。

合并索引碎片

SQL> alter index emp_ename_idx coalesce;

索引已更改。

删除索引

SQL> drop index emp_name_sal_index;

索引已删除。

SQL> select index_name,pct_free,pct_increase,initial_extent,next_extent from  user_indexes;

INDEX_NAME                                                                                   PCT_FREE PCT_INCREASE INITIAL_EXTENT NEXT_EXTENT
------------------------------------------------------------------------------------------ ---------- ------------ -------------- -----------
PK_EMP                                                                                             10                       65536     1048576
IDX_SAL_EMP                                                                                        10                       65536     1048576
EMP_ENAME_IDX                                                                                      10                       65536     1048576
PK_DEPT                                                                                            10                       65536     1048576

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值