oracle 索引概述

一. 概念
(1) 類似書的目錄結構,可以提高數據檢索的速度
(2) 索引直接指向包含所查詢值的行的位置,減少磁盤I/O
(3) 索引與表在物理上獨立,Oracle 自動使用並維護索引,插入、刪除、更新表後,自動更新索引
(4) 建立索引時,要考慮好索引的存儲開銷與性能上的獲益之間的比重,不要盲目建立索引

二.分類

1.唯一索引

當建立Primary Key(主鍵)或者Unique constraint(唯一約束)時,唯一索引將被自動建立
唯一索引可爲空,但不爲空時,值需都不相同。
語法:CREATE UNIQUE INDEX index_name ON table (column);

2.組合索引
當兩個或多個列經常一起出現在where條件中時,則在這些列上創建組合索引

(1)RBO 下 where 子句爲非前導列
rbo下where爲非前導列時,執行計劃不走索引。
SQL> explain plan for select /*+rule*/* from t1 where c2=1;
Explained

SQL> select * from table (dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3617692013
----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|*  1 |  TABLE ACCESS FULL| T1   |
----------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("C2"=1)
Note
-----
   - rule based optimizer used (consider using cbo)
17 rows selected

(2)CBO 下 where 子句爲非前導列
從9i起,oracle在cbo下引入了索引跳躍掃描(index skip scan),即使SQL語句的where子句中沒有組合索引的前導列,也能使用該索引。
SQL> explain plan for select * from t1 where c2=2;
Explained

SQL> select * from table (dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    26 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |     1 |    26 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("C2"=2)
Note
-----
   - dynamic sampling used for this statement
17 rows selected


10053事件跟蹤sql,部分信息如下:

  Table: T1  Alias: T1    
    Card: Original: 10000  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00
  Access Path: TableScan
    Cost:  6.40  Resp: 6.40  Degree: 0
      Cost_io: 6.00  Cost_cpu: 2342429
      Resp_io: 6.00  Resp_cpu: 2342429
  Access Path: index (index (FFS))
    Index: INDEX_T1
    resc_io: 8.00  resc_cpu: 1927886
    ix_sel: 0.0000e+000  ix_sel_with_filters: 1
  Access Path: index (FFS)
    Cost:  8.33  Resp: 8.33  Degree: 1
      Cost_io: 8.00  Cost_cpu: 1927886
      Resp_io: 8.00  Resp_cpu: 1927886
kkofmx: index filter:"T1"."C2"=2
  Access Path: index (FullScan)
    Index: INDEX_T1
    resc_io: 33.00  resc_cpu: 2235008
    ix_sel: 1  ix_sel_with_filters: 1
    Cost: 33.47  Resp: 33.47  Degree: 1
  Best:: AccessPath: TableScan
         Cost: 6.40  Degree: 1  Resp: 6.40  Card: 1.00  Bytes: 0

測試中oracle執行計劃有考慮索引時的情況,但全表掃描代價最小,oracle選擇全表掃描

3.位圖索引

與傳統的b-tree 索引不同,位圖索引由鍵值和鍵值所在的rowid構成,多用於olap。
(1)位圖索引dml操作會鎖定其他行,b-tree索引只會鎖定本行,位圖索引不適用於頻繁更新的oltp
(2)位圖索引允許爲null,is null時仍能生效,b-tree索引不可以。
(3)每個位圖爲表中的每一個記錄包含一個位(0或1),1表示包含該值,0表示不包含。用 and or 或in 做鍵值運算。
e.g
createtable t2(c1 varchar2(10),c2 varchar(10));
create bitmap index bit_index_t2_c1 on t2(c1);
create bitmap index bit_index_t2_c2 on t2(c2);
insert into t2 values( 'a','男' );
insert into t2 values( 'b','女' );
insert into t2 values( 'c','男' );
c1列中數據
a  b   c
1  0   0
0  1   0
0   0  1

c2列中數據
男    女
1      0
0      1
1      0

select * from t2 where c1='b' and c2='女' 等價於
b        女
1 and  1   =  1


 (4)適用於相異數據較少的列,如性別,不適用與唯一索引。

4.基於函數的索引

在WHERE條件語句中包含函數或者表達式時,若該字段上有索引,該索引不生效,此時可建立基於此字段的函數索引來提高性能。
函數包括:算數表達式、PL/SQL函數、程序包函數、SQL函數、用戶自定義函數。

e.g
create table t3(c1 varchar2( 10),c2 varchar (10));
insert into t3 values( '1','wuhen' );
insert into t3 values( '2','hello' );
insert into t3 values( '3','world' );
create index index_t3 on t3(c2);
SQL> explain plan for select * from t3 where upper(c2)='WUHEN';
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2574254479
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    14 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T3   |     1 |    14 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
此時c2上索引沒有被使用。
SQL> drop index index_t3;
Index dropped

創建基於函數的索引
SQL> create index index_t3 on t3(upper(c2));
Index created

SQL> explain plan for select * from t3 where upper(c2)='WUHEN';\
Explained

SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2208359772
--------------------------------------------------------------------------------
| Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Ti
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |     1 |    14 |     1   (0)| 00
|   1 |  TABLE ACCESS BY INDEX ROWID| T3       |     1 |    14 |     1   (0)| 00
|*  2 |   INDEX RANGE SCAN          | INDEX_T3 |     1 |       |     1   (0)| 00
--------------------------------------------------------------------------------
此時c2上的函數索引被使用

5.反向鍵索引
比如索引值是一個自動增長的列,反向鍵索引能減少索引層數;多個用戶對集中在少數塊上的索引行進行修改,容易引起資源的爭用,比如對數據塊的等待,此時建立方向鍵索引能提高性能。當範圍索引between,>,< 將導致全表掃描。

6.索引組織表(IOT)
將表中的數據按照索 引的結構存儲在索引中,提高查詢速度。
犧牲插入更新的性能,換取查詢 性能。通常用於數據倉庫,提供大量的查詢,極少的插入修改工作。
必須指定主鍵。插入數據時,會根據主鍵列進行B樹索引排序,寫入磁盤。

7. 分區索引
表可以按range、hash、list分區,表分區後,其上的索引和普通表上的索引有所不同,oracle對於分區表上的索引分爲局部索引和全局索引
局部索引一定是分區索引,分有前綴索引和無前綴索引,常用與olap
全局索引可以依附分區表,也可以是非分區表,但一定是有前綴索引

三.操作
1.創建
alter table 用來創建普通索引、UNIQUE索引或PRIMARY KEY索引。

alter table tablename add constraint indexname primary key(column)

create index用來創建普通索引、UNIQUE索引或PRIMARY KEY索引。

CREATE INDEX index_name ON table_name (column_list)

CREATE UNIQUE INDEX index_name ON table_name (column_list)

2.刪除 
DROP INDEX index_name;

ALTER TABLE table_name DROP INDEX index_name;

ALTER TABLE table_name DROP PRIMARY KEY;


四.索引失效
1.索引上爲null
解決辦法,設置not null 或用0代替

2.索引上類型不匹配,隱式數據類型轉換
a varchar2
select from where a=1 ---隱式轉換,沒有用到索引
select from where a='1' --非隱式轉換,用到索引

3.索引列上計算,或使用函數
select from where 12*a=12;

4.select from where a like '%abc';

5.使用!=或 <>
e.g
select * from t1 where t1!='a';
改爲
select * from t1 where t1>'a' and t1<'a';
發佈了26 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章