日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ORACLE B-TREE(B树)索引

發(fā)布時間:2023/12/18 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ORACLE B-TREE(B树)索引 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

內(nèi)容簡介:

1.普通B-TREE 索引;

2.唯一B-TREE 索引;

3.復(fù)合索引;

ORACLE 默認(rèn)的索引類型為B-TREE 索引,表中的行標(biāo)識符(ROWID)和行相關(guān)的列值被存儲在一個平衡樹的樹狀結(jié)構(gòu)的索引塊中;使用B-TREE索引有以下幾個原因:

? 提高SQL語句的性能;

? 強(qiáng)制執(zhí)行主鍵和唯一鍵約束的唯一性;

? 減少通過主鍵和外鍵約束關(guān)聯(lián)的父表和子表間潛在的鎖定問題 ;

1.普通B-TREE 索引

在一張未建立任何索引的500萬行人員信息表中根據(jù)人員ID查詢?nèi)藛T信息

select id,name,gender,homeaddr from th01 where id=998698;

--------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

--------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 38 | 16715 (1)| 00:03:21 |

|* 1 | TABLE ACCESS FULL| TH01 | 1 | 38 | 16715 (1)| 00:03:21 |

--------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter("ID"=998698)

Statistics

----------------------------------------------------------

61222 consistent gets

61208 physical reads

通過觀察執(zhí)行計劃,CBO優(yōu)化器執(zhí)行了全表掃描,一致讀取61222個塊,61208個物理讀,基于性能的考慮和表結(jié)構(gòu)的分析,為其B-TREE索引:

SQL> CREATE INDEX IND_TH01_ID ON TH01(ID) TABLESPACE TBS02;

Index created.

Elapsed: 00:00:33.03

SQL> execute dbms_stats.gather_table_stats('sywu','th01',cascade=>true);

PL/SQL procedure successfully completed.

Elapsed: 00:00:04.17

SQL> @/oracle/getind

TABLE_NAME ? ? INDEX_NAME ?? COLUMN_NAME??? SIZE_GB ?? INDEX_TY ? STATUS ?? LOGGING ?? DEGREE ?? NUM_ROWS ?? DISTINCT_KEYS

------------------------------ ------------------------------ ------------------------------ ---------- -------- -------- --------- ---------- -------- ---------- ------------- ---

TH01?? ? ? ? ? ? ? ? ?? IND_TH01_ID????????? ID ? ? ? ? ? ? ? ? ?? .091796875 ? ? ? NORMAL VALID ? ? ? ? ? ? YES ? ? ? ? ? ? ? 1 ? ? ? ? ?? DISABLED ? ? ?? 5000000 ? 5000000

顯然對于高基數(shù)的列創(chuàng)建B-TREE索引是明智之選,對表進(jìn)行分析后再次查詢:

SQL>select id,name,gender,homeaddr from th01 where id=998698;

Elapsed: 00:00:00.00

-------------------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

-------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 38 | 4 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 38 | 4 (0)| 00:00:01 |

|* 2 | INDEX RANGE SCAN | IND_TH01_ID | 1 | | 3 (0)| 00:00:01 |

------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("ID"=998698)

Statistics

----------------------------------------------------------

5 consistent gets

0 physical reads

基于成本的考慮,CBO優(yōu)化器選擇了通過索引的方式讀取數(shù)據(jù),一致讀取5個塊,有效減少了額外的物理讀;做個基于索引列的統(tǒng)計查詢:

SQL> select count(id) from th01;

Elapsed: 00:00:00.15

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

-------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 6 | 3170 (1)| 00:00:39 |

| 1 | SORT AGGREGATE | | 1 | 6 | | |

| 2 | INDEX FAST FULL SCAN| IND_TH01_ID | 5000K| 28M| 3170 (1)| 00:00:39 |

-------------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

11810 consistent gets

11794 physical reads

CBO 優(yōu)化器選擇了全索引掃描,依舊消耗額外的資源;但當(dāng)統(tǒng)計列發(fā)生改變時:

SQL> select count(*) from th01;

Elapsed: 00:00:00.14

-------------------------------------------------------------------

| Id | Operation | Name | Rows | Cost (%CPU)| Time |

-------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 16707 (1)| 00:03:21 |

| 1 | SORT AGGREGATE | | 1 | | |

| 2 | TABLE ACCESS FULL| TH01 | 5000K| 16707 (1)| 00:03:21 |

Statistics

----------------------------------------------------------

61221 consistent gets

61208 physical reads

此時CBO 優(yōu)化器選擇了全表掃描,并消耗更多的資源;


2.唯一B-TREE 索引:

在為表創(chuàng)建(主鍵、唯一約束),ORACLE 會默認(rèn)創(chuàng)建一個B-TREE索引,這樣既保證了數(shù)據(jù)的唯一性也提高了數(shù)據(jù)的檢索效率:

SQL> alter table th01 add constraints cs_th01_uq unique(idcard);

Table altered.

Elapsed: 00:00:56.11

TABLE_NAME ? ?? INDEX_NAME ? ? COLUMN_NAME ? ? SIZE_GB??? INDEX_TY ? ?? STATUS ? ? LOGGING ? ? ?? DEGREE ?? COMPRESS ?? NUM_ROWS ?? DISTINCT_KEYS

------------------------------ ------------------------------ ------------------------------ ---------- -------- -------- --------- ---------- -------- ---------- ------------- ---

TH01 ? ? ? ? ? ? CS_TH01_UQ ? ? ? ? ? ? ? ?? IDCARD??????????????? .15625 ? ? ? ? ? ? ? NORMAL ? VALID????????????? YES ? ? ? ? ? ? ? ?? 1 ? ? ? ? ? ?? DISABLED ?? 4969898 ? ? ? ? ? 4969898

IDCARD查詢?nèi)藛T信息:

------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 35 | 3 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 35 | 3 (0)| 00:00:01 |

|* 2 | INDEX UNIQUE SCAN | CS_TH01_UQ | 1 | | 2 (0)| 00:00:01 |

------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("IDCARD"='562456864646565545')

Statistics

----------------------------------------------------------

3 consistent gets

0 physical reads

做為默認(rèn)創(chuàng)建的索引,它依舊能高效的工作,ORACLE是不允許將其作為獨(dú)立的索引刪除的,只能通過刪除約束的方式刪除;對于主鍵,它的情況要復(fù)雜些,因?yàn)檫€要考慮外鍵的約束;基于這種方式創(chuàng)建的索引,當(dāng)約束被刪除時還要重新創(chuàng)建索引,顯然在一張大表上花費(fèi)的代價和時間是昂貴的; so,采用如下的方式合理的建立約束和索引:

SQL> alter table th01 add constraints CS_TH01_UQ unique(idcard)

2* using index tablespace tbs03 ;

Table altered.

Elapsed: 00:00:59.27

倘若有一天業(yè)務(wù)發(fā)生了改變,唯一約束已經(jīng)不是必須的,但索引是必須的,那只需要刪除約束保留索引:

SQL> alter table th01 drop constraints CS_TH01_UQ keep index;

Table altered.

Elapsed: 00:00:00.01

再次通過IDCARD 查詢?nèi)藛T信息:

SQL> select id,name,idcard from th01 where idcard='56234256878945';

------------------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 35 | 3 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 35 | 3 (0)| 00:00:01 |

|* 2 | INDEX UNIQUE SCAN | CS_TH01_UQ | 1 | | 2 (0)| 00:00:01 |

------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("IDCARD"='56234256878945')

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

3 consistent gets


只創(chuàng)建唯一索引:

SQL> create unique index ind_th02 on th02(idcard) tablespace tbs03;

唯一索引與唯一約束相比,唯一索引只創(chuàng)建索引而不添加約束,它保證索引列數(shù)值唯一性,允許有空值;


3.復(fù)合索引:

可以在多個列上創(chuàng)建索引,其結(jié)果稱為復(fù)合索引或組合索引:

SQL> create index ind_th01_union on th01(id,name,idcard) tablespace tbs03;

當(dāng)查詢的WHERE子句引用了索引的所有列或者只是前導(dǎo)列,CBO會使用復(fù)合索引

SQL>select id,name,idcard from th01 where idcard='9876534655635666' and id=68956254 and name='張三';

-----------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

-----------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 35 | 3 (0)| 00:00:01 |

|* 1 | INDEX RANGE SCAN| IND_TH01_UNION | 1 | 35 | 3 (0)| 00:00:01 |

-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - access("ID"=68956254 AND "NAME"='張三' AND

"IDCARD"='9876534655635666')

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

3 consistent gets

2 physical reads

通過查詢結(jié)果,對于之前創(chuàng)建的單列索引(IND_TH01_IDCS_TH01_UQ),優(yōu)化器已不再使用;對于復(fù)合索引( IND_TH01_UNION) 來說, id | id, name| id,name,idcard 三個組合都被認(rèn)為是前導(dǎo)列,假如我只是在WHERE 子句中引用了第一個主導(dǎo)列ID,那么優(yōu)化器依舊會選擇復(fù)合索引(IND_TH01_UNION )忽略單列索引( IND_TH01_ID)

SQL> select * from th01 where id=698698;

----------------------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

----------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 77 | 4 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 77 | 4 (0)| 00:00:01 |

|* 2 | INDEX RANGE SCAN | IND_TH01_UNION | 1 | | 3 (0)| 00:00:01 |

----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("ID"=698698)

Statistics

----------------------------------------------------------

0 db block gets

5 consistent gets

?

假如where 子句中的條件不符合復(fù)合索引前導(dǎo)列的要求,那么優(yōu)化器會忽略復(fù)合索引( IND_TH01_UNION)選擇單列索引(CS_TH01_UQ):

SQL> select * from th01 where idcard='5623546566564665';

------------------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 77 | 3 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 77 | 3 (0)| 00:00:01 |

|* 2 | INDEX UNIQUE SCAN | CS_TH01_UQ | 1 | | 2 (0)| 00:00:01 |

------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("IDCARD"='5623546566564665')

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

3 consistent gets

1 physical reads

對于此時的查詢條件 where idcard='5623546566564665' 已經(jīng)不再符合( id | id, name| id,name,idcard) 復(fù)合索引前導(dǎo)列的條件,優(yōu)化器選擇單列索引( CS_TH01_UQ);又假如,我的WHERE 子句條件符合復(fù)合索引前導(dǎo)列要求但不是全部滿足:

SQL> select * from th01 where id=698698 and name='張三';

----------------------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

----------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 77 | 4 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 77 | 4 (0)| 00:00:01 |

|* 2 | INDEX RANGE SCAN | IND_TH01_UNION | 1 | | 3 (0)| 00:00:01 |

----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

2 - access("ID"=698698 AND "NAME"='張三')

Statistics

----------------------------------------------------------

3 consistent gets

0 physical reads

通過分析(where id=698698 and name='張三' )符合復(fù)合索引前導(dǎo)列要求,優(yōu)化器選擇復(fù)合索引( IND_TH01_UNION) 忽略單列索引( IND_TH01_ID);

創(chuàng)建復(fù)合索引時,排序是個很大的問題,ORACLE 建議將最頻繁訪問的列放在索引中最靠前的位置,應(yīng)避免使用低基數(shù)的列作為復(fù)合索引的前導(dǎo)列.

?




轉(zhuǎn)載于:https://www.cnblogs.com/lanston/p/3485466.html

總結(jié)

以上是生活随笔為你收集整理的ORACLE B-TREE(B树)索引的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。