中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Oracle中組合索引怎么用

發布時間:2021-11-09 14:58:11 來源:億速云 閱讀:364 作者:小新 欄目:關系型數據庫

這篇文章給大家分享的是有關Oracle中組合索引怎么用的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

Oracle中組合索引的使用

關鍵詞:組合索引 前導列  基于規則的優化器(RBO  基于成本的優化器(CBO  提示(hint

Oracle中可以創建組合索引,即同時包含兩個或兩個以上列的索引。在組合索引的使用方面,Oracle有以下特點:

1、   當使用基于規則的優化器(RBO)時,只有當組合索引的前導列出現在SQL語句的where子句中時,才會使用到該索引;

2、   在使用Oracle9i之前的基于成本的優化器(CBO)時, 只有當組合索引的前導列出現在SQL語句的where子句中時,才可能會使用到該索引,這取決于優化器計算的使用索引的成本和使用全表掃描的成本,Oracle會自動選擇成本低的訪問路徑(請見下面的測試1和測試2);

3、   Oracle9i起,Oracle引入了一種新的索引掃描方式——索引跳躍掃描(index skip scan),這種掃描方式只有基于成本的優化器(CBO)才能使用。這樣,當SQL語句的where子句中即使沒有組合索引的前導列,并且索引跳躍掃描的成本低于其他掃描方式的成本時,Oracle就會使用該方式掃描組合索引(請見下面的測試3);

4、   Oracle優化器有時會做出錯誤的選擇,因為它再“聰明”,也不如我們SQL語句編寫人員更清楚表中數據的分布,在這種情況下,通過使用提示(hint),我們可以幫助Oracle優化器作出更好的選擇(請見下面的測試4)。

[@more@]

關于以上情況,我們分別測試如下:

我們創建測試表T,該表的數據來源于Oracle的數據字典表all_objects,表T的結構如下:

SQL> desc t

名稱                                      是否為空? 類型

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

OWNER                                     NOT NULL VARCHAR2(30)

OBJECT_NAME                               NOT NULL VARCHAR2(30)

SUBOBJECT_NAME                                     VARCHAR2(30)

OBJECT_ID                                 NOT NULL NUMBER

DATA_OBJECT_ID                                     NUMBER

OBJECT_TYPE                                        VARCHAR2(18)

CREATED                                   NOT NULL DATE

LAST_DDL_TIME                             NOT NULL DATE

TIMESTAMP                                          VARCHAR2(19)

STATUS                                             VARCHAR2(7)

TEMPORARY                                          VARCHAR2(1)

GENERATED                                          VARCHAR2(1)

SECONDARY                                          VARCHAR2(1)

表中的數據分布情況如下:

SQL> select object_type,count(*) from t group by object_type;

OBJECT_TYPE          COUNT(*)

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

CONSUMER GROUP             20

EVALUATION CONTEXT         10

FUNCTION                  360

INDEX                      69

LIBRARY                    20

LOB                        20

OPERATOR                   20

PACKAGE                  1210

PROCEDURE                 130

SYNONYM                 16100

TABLE                     180

TYPE                     2750

VIEW                     8600

已選擇13行。

SQL> select count(*) from t;

 COUNT(*)

----------

    29489

我們在表T上創建如下索引并對其進行分析:

SQL> create index indx_t on t(object_type,object_name);

索引已創建。

SQL> ANALYZE TABLE T COMPUTE STATISTICS

 2    FOR TABLE

 3    FOR ALL INDEXES

 4    FOR ALL INDEXED COLUMNS

 5  /

表已分析。

現在讓我們編寫幾條SQL語句來測試一下Oracle優化器對訪問路徑的選擇:

測試1

SQL> set autotrace traceonly

SQL> SELECT * FROM T WHERE OBJECT_TYPE='LOB';

已選擇20行。

Execution Plan

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

  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=22 Card=20 Bytes=1740)

  1    0   TABLE ACCESS (BY INDEX ROWID) OF 'T' (Cost=22 Card=20 Bytes=1740)

  2    1     INDEX (RANGE SCAN) OF 'INDX_T' (NON-UNIQUE) (Cost=2 Card=20)

正如我們所期望的,由于使用了組合索引的前導列并且訪問了表中的少量記錄,Oracle明智地選擇了索引掃描。那么,如果我們訪問表中的大量數據時,Oracle會選擇什么樣的訪問路徑呢?請看下面的測試:

測試2

SQL> SELECT * FROM T WHERE OBJECT_TYPE='SYNONYM';

已選擇16100行。

Execution Plan

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

  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=38 Card=16100 Bytes=1400700)

 1    0   TABLE ACCESS (FULL) OF 'T' (Cost=38 Card=16100 Bytes=1400700)

Statistics

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

         0  recursive calls

         0  db block gets

      1438  consistent gets

        13  physical reads

         0  redo size

    941307  bytes sent via SQL*Net to client

     12306  bytes received via SQL*Net from client

      1075  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

     16100  rows processed

很明顯,即使使用了組合索引的前導列,但是由于訪問了表中的大量數據,Oracle選擇了不使用索引而直接使用全表掃描,因為優化器認為全表掃描的成本更低,但事實是不是真的這樣的?我們通過增加提示(hint)來強制它使用索引來看看:

SQL> SELECT/*+ INDEX (T INDX_T)*/ * FROM T WHERE OBJECT_TYPE='SYNONYM';

已選擇16100行。

Execution Plan

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

  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=16180 Card=16100 Bytes=1400700)

  1    0   TABLE ACCESS (BY INDEX ROWID) OF 'T' (Cost=16180 Card=16100 Bytes=1400700)

  2    1     INDEX (RANGE SCAN) OF 'INDX_T' (NON-UNIQUE) (Cost=80 Card=16100)

Statistics

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

         0  recursive calls

         0  db block gets

     17253  consistent gets

        16  physical reads

         0  redo size

    298734  bytes sent via SQL*Net to client

     12306  bytes received via SQL*Net from client

      1075  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

     16100  rows processed

從以上結果可以看出,在訪問大量數據的情況下,使用索引確實會導致更高的執行成本,這從statistics部分的邏輯讀取數(consistent gets)就可以看出,使用索引導致的邏輯讀取數是不使用索引導致的邏輯讀的10倍還多。因此,Oracle明智地選擇了全表掃描而不是索引掃描。

下面,讓我們來看看where子句中沒有索引前導列的情況:

測試3

SQL> select * from t where object_name= 'DEPT';

已選擇10行。

Execution Plan

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

  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=29 Card=14 Bytes=1218)

  1    0   TABLE ACCESS (BY INDEX ROWID) OF 'T' (Cost=29 Card=14 Bytes=1218)

  2    1    INDEX (SKIP SCAN) OF 'INDX_T' (NON-UNIQUE) (Cost=14 Card=14)

Statistics

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

         0  recursive calls

         0  db block gets

        24  consistent gets

         0  physical reads

         0  redo size

      1224  bytes sent via SQL*Net to client

       503  bytes received via SQL*Net from client

         2  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

        10  rows processed

OK!由于只查詢了10條數據,即使沒有使用前導列,Oracle正確地選擇了索引跳躍掃描。我們再來看看如果不使用索引跳躍掃描,該語句的成本:

SQL> select/*+ NO_INDEX(T INDX_T)*/ * from t where object_name= 'DEPT';

已選擇10行。

Execution Plan

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

  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=38 Card=14 Bytes=1218)

  1    0   TABLE ACCESS (FULL) OF 'T' (Cost=38 Card=14 Bytes=1218)

Statistics

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

         0  recursive calls

         0  db block gets

       375  consistent gets

        17  physical reads

         0  redo size

      1224  bytes sent via SQL*Net to client

       503  bytes received via SQL*Net from client

         2  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

        10  rows processed

正如我們所料,不使用索引所導致的邏輯讀(375)確實比使用索引的邏輯讀多(24),達到10倍以上。

繼續我們的測試,現在我們來看看Oracle不選擇使用索引的情況:

測試4

SQL> select * from t where object_name LIKE  'DE%';

已選擇180行。

Execution Plan

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

  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=38 Card=37 Bytes=3219)

  1    0   TABLE ACCESS (FULL) OF 'T' (Cost=38 Card=37 Bytes=3219)

Statistics

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

         0  recursive calls

         0  db block gets

       386  consistent gets

        16  physical reads

         0  redo size

     12614  bytes sent via SQL*Net to client

       624  bytes received via SQL*Net from client

        13  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

       180  rows processed

這次只選擇了180條數據,跟表T中總的數據量29489條相比,顯然只是很小的一部分,但是Oracle還是選擇了全表掃描,有386個邏輯讀。這種情況下,如果我們強制使用索引,情況會怎樣呢?

SQL> select/*+ INDEX(T INDX_T)*/ * from t where object_name LIKE  'DE%';

已選擇180行。

Execution Plan

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

  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=182 Card=37 Bytes=3219)

  1    0   TABLE ACCESS (BY INDEX ROWID) OF 'T' (Cost=182 Card=37 Bytes=3219)

  2    1     INDEX (FULL SCAN) OF 'INDX_T' (NON-UNIQUE) (Cost=144 Card=37)

Statistics

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

         0  recursive calls

         0  db block gets

       335  consistent gets

         0  physical reads

         0  redo size

      4479  bytes sent via SQL*Net to client

       624  bytes received via SQL*Net from client

        13  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

       180  rows processed

通過添加提示(hint),我們強制Oracle使用了索引掃描(index full scan),執行了335個邏輯讀,比使用全表掃描的時候少了一些。

由此可見,Oracle優化器有時會做出錯誤的選擇,因為它再“聰明”,也不如我們SQL語句編寫人員更清楚表中數據的分布,在這種情況下,通過使用提示(hint),我們可以幫助Oracle優化器作出更好的選擇。

感謝各位的閱讀!關于“Oracle中組合索引怎么用”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

延川县| 调兵山市| 沈丘县| 渝中区| 郁南县| 南木林县| 德阳市| 顺义区| 宜良县| 沧州市| 福鼎市| 长宁县| 黄大仙区| 乌兰浩特市| 电白县| 台北县| 观塘区| 麦盖提县| 廊坊市| 平乐县| 日喀则市| 特克斯县| 潼南县| 扎鲁特旗| 布拖县| 舞钢市| 雅安市| 米林县| 体育| 常州市| 大方县| 天祝| 永顺县| 安平县| 化州市| 宜章县| 瑞丽市| 彰化市| 喀喇沁旗| 灵宝市| 长乐市|