溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何解決索引掃描時(shí)對(duì)同一個(gè)葉子塊訪問多次的問題

發(fā)布時(shí)間:2021-10-09 16:50:26 來源:億速云 閱讀:131 作者:iii 欄目:數(shù)據(jù)庫

本篇內(nèi)容介紹了“如何解決索引掃描時(shí)對(duì)同一個(gè)葉子塊訪問多次的問題”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

如何解決索引掃描時(shí)對(duì)同一個(gè)葉子塊訪問多次的問題

先創(chuàng)建以下測(cè)試環(huán)境,以重現(xiàn)相關(guān)現(xiàn)象。創(chuàng)建測(cè)試表,其中C1列為CHAR(256),目的是使該列占用字節(jié)數(shù)較多,使得后面在該列上創(chuàng)建索引時(shí),可以用較少的行數(shù)構(gòu)建出2層的索引。

SQL> create table test0429 (id number,c1 char(256),v1 varchar2(256));  Table created.

C1中插入的值為‘01’+254個(gè)空格,‘02’+254個(gè)空格…這樣的值。

SQL> insert into test0429 select rownum id,lpad(rownum,2,'0') c1,rownum v1 from dual connect by rownum<=50;  50 rows created.   SQL> commit;  Commit complete.

在C1列上創(chuàng)建索引:

SQL> create index ind_test0429_c1 on test0429(c1);  Index created.

查詢?cè)撍饕腛BJECT_ID,以便查看其樹形結(jié)構(gòu)。

SQL> select object_id,object_name,object_type from user_objects where object_name='IND_TEST0429_C1';   OBJECT_ID OBJECT_NAME                 OBJECT_TYPE ---------- ----------------------------------- -------------------      97504 IND_TEST0429_C1             INDEX   SQL> alter session set events 'immediate trace name treedump level 97504';  Session altered.  SQL> select * from v$diag_info;     INST_ID NAME ---------- ---------------------------------------------------------------- VALUE --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------      1 Diag Enabled TRUE       1 ADR Base /oradata/app/oracle       1 ADR Home /oradata/app/oracle/diag/rdbms/orcl/orcl       1 Diag Trace /oradata/app/oracle/diag/rdbms/orcl/orcl/trace       1 Diag Alert /oradata/app/oracle/diag/rdbms/orcl/orcl/alert       1 Diag Incident /oradata/app/oracle/diag/rdbms/orcl/orcl/incident       1 Diag Cdump /oradata/app/oracle/diag/rdbms/orcl/orcl/cdump       1 Health Monitor /oradata/app/oracle/diag/rdbms/orcl/orcl/hm       1 Default Trace File /oradata/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_2751.trc       1 Active Problem Count 5       1 Active Incident Count 17   11 rows selected.

在對(duì)應(yīng)的跟蹤文件中,看到的索引結(jié)構(gòu)為1個(gè)根節(jié)點(diǎn),2個(gè)葉子節(jié)點(diǎn)。如下所示:

----- begin tree dump branch: 0x180414b 25182539 (0: nrow: 2, level: 1)    leaf: 0x180414c 25182540 (-1: nrow: 26 rrow: 26)    leaf: 0x180414d 25182541 (0: nrow: 24 rrow: 24) ----- end tree dump

查詢根節(jié)點(diǎn)和最左側(cè)葉子節(jié)點(diǎn)的數(shù)據(jù)塊所在文件塊及塊號(hào),準(zhǔn)備DUMP其數(shù)據(jù)塊,以便查看其中的內(nèi)容。

SQL> select DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(to_number('&&p3_value','xxxxxxxx')) FILE#,        DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(to_number('&&p3_value','xxxxxxxx')) BLOCK# from dual;  2    3   Enter value for p3_value: 180414b old   1: select DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(to_number('&&p3_value','xxxxxxxx')) FILE#, new   1: select DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(to_number('180414b','xxxxxxxx')) FILE#, old   2:    DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(to_number('&&p3_value','xxxxxxxx')) BLOCK# new   2:    DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(to_number('180414b','xxxxxxxx')) BLOCK#       FILE#     BLOCK# ---------- ----------      6  16715  SQL> undefine p3_value SQL> select DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(to_number('&&p3_value','xxxxxxxx')) FILE#,        DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(to_number('&&p3_value','xxxxxxxx')) BLOCK# from dual;   2    3   Enter value for p3_value: 180414c old   1: select DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(to_number('&&p3_value','xxxxxxxx')) FILE#, new   1: select DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(to_number('180414c','xxxxxxxx')) FILE#, old   2:    DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(to_number('&&p3_value','xxxxxxxx')) BLOCK# new   2:    DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(to_number('180414c','xxxxxxxx')) BLOCK#       FILE#     BLOCK# ---------- ----------      6  16716

DUMP根塊和最左側(cè)葉子塊中的內(nèi)容到跟蹤文件中。

SQL> alter system dump datafile 6 block min 16715 block max 16716;  System altered.

從跟蹤文件中,可以看到根塊中的主要內(nèi)容如下所示(為節(jié)省篇幅,以下只列出與本主題相關(guān)的主要內(nèi)容,以下其它類似內(nèi)容亦做了相關(guān)處理,不再重復(fù)說明):

kdxcolev 1 KDXCOLEV Flags = - - - kdxcolok 0 kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y kdxconco 2 kdxcosdc 0 kdxconro 1 kdxcofbo 30=0x1e kdxcofeo 8048=0x1f70 kdxcoavs 8018 kdxbrlmc 25182540=0x180414c kdxbrsno 0 kdxbrbksz 8056 kdxbr2urrc 3 row#0[8048] dba: 25182541=0x180414d col 0; len 2; (2):  32 37 col 1; TERM ----- end of branch block dump -----

從上面的倒數(shù)第三行的內(nèi)容中可知,最右側(cè)的葉子塊中的最小索引鍵值為&lsquo;27&rsquo;+254個(gè)空格。

從跟蹤文件中,可以看到最左側(cè)葉子塊中的主要內(nèi)容如下所示:

kdxcolev 0 KDXCOLEV Flags = - - - kdxcolok 0 kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y kdxconco 2 kdxcosdc 0 kdxconro 26 kdxcofbo 88=0x58 kdxcofeo 1090=0x442 kdxcoavs 1002 kdxlespl 0 kdxlende 0 kdxlenxt 25182541=0x180414d kdxleprv 0=0x0 kdxledsz 0 kdxlebksz 8032 row#0[7765] flag: ------, lock: 0, len=267 col 0; len 256; (256):  30 31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ......  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  20 20 20 20 20 20 col 1; len 6; (6):  01 80 41 47 00 00 row#1[7498] flag: ------, lock: 0, len=267 col 0; len 256; (256):  30 32 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ...... row#25[1090] flag: ------, lock: 0, len=267 col 0; len 256; (256):  32 36 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ......  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  20 20 20 20 20 20 col 1; len 6; (6):  01 80 41 47 00 19 ----- end of leaf block dump ----- End dump data blocks tsn: 7 file#: 6 minblk 16715 maxblk 16716

為跟蹤索引數(shù)據(jù)塊被訪問的情況,打開10200跟蹤事件。

SQL> alter session set events '10200 trace name context forever,level 1';  Session altered.

查詢位于最左側(cè)葉子塊中的數(shù)據(jù),由于是等值查詢,且C1列上無重復(fù)值,故以下查詢會(huì)返回1行。

SQL> set lines 200 pages 60  SQL> select c1 from test0429 where c1='01';                                                                       C1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 01

由于我們?cè)贑1列上創(chuàng)建的索引不是唯一索引,所以此時(shí),對(duì)索引的訪問方法為索引范圍掃描。如下圖所示:

SQL> select * from table(dbms_xplan.display_cursor('','','typical'));  PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SQL_ID  3kt1uqh383qbx, child number 0 ------------------------------------- select c1 from test0429 where c1='01'  Plan hash value: 1267036809  ------------------------------------------------------------------------------------ | Id  | Operation        | Name            | Rows  | Bytes | Cost (%CPU)| Time     | ------------------------------------------------------------------------------------ |   0 | SELECT STATEMENT |                 |       |       |     1 (100)|          | |*  1 |  INDEX RANGE SCAN| IND_TEST0429_C1 |     1 |   257 |     1   (0)| 00:00:01 | ------------------------------------------------------------------------------------   Predicate Information (identified by operation id): ---------------------------------------------------     1 - access("C1"='01')   18 rows selected.

查看10200跟蹤文件中的輸出,我們可以看到先訪問了索引根塊,然后訪問了最左側(cè)的葉子塊。這是符合預(yù)期的。但我們可以看到,最左側(cè)的葉子塊訪問了2次。

ktrgtc2(): started for block <0x0007 : 0x0180414b> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0

之所以被訪問兩次,我認(rèn)為其過程如下:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 訪問索引根塊,即訪問“block <0x0007 : 0x0180414b>”;

  3. 由于條件值&lsquo;01&rsquo;小于根塊中,指向第二個(gè)葉子塊的索引條目中的值&lsquo;27&rsquo;,所以,需要訪問索引最左側(cè)的葉子塊,即訪問“<0x0007 :  0x0180414c>”;

  4. 在最左側(cè)的葉子塊中找到了第一行滿足條件的記錄ROW0。暫停繼續(xù)掃描,而將第一行返回;

  5. 繼續(xù)在最左側(cè)的葉子塊中查找是否有滿足條件的記錄。所以,會(huì)再次訪問最左側(cè)的葉子塊;

  6. 在訪問ROW1時(shí),得到了值&lsquo;02&rsquo;+254個(gè)空格,該值大于&lsquo;01&rsquo;,故整個(gè)索引中已不會(huì)再有滿足條件的記錄,所以,結(jié)束掃描,退出;

  7. 如果在葉子塊的掃描中,還能繼續(xù)找到滿足條件值的記錄,就不是每找到一行,就暫停掃描并返回當(dāng)前結(jié)果了,而是根據(jù)ARRAYSIZE中的值,每湊夠該參數(shù)指定的行數(shù),才會(huì)暫停掃描并返回結(jié)果,然后再繼續(xù)掃描。當(dāng)發(fā)生“再繼續(xù)掃描”這個(gè)動(dòng)作時(shí),相應(yīng)的葉子塊會(huì)被再一次訪問。

針對(duì)6中所述,我們進(jìn)行如下測(cè)試。將ARRAYSIZE設(shè)置為3,即每湊夠3行即暫停掃描,返回結(jié)果。而該參數(shù)的默認(rèn)值為15。

SQL> show arraysize arraysize 15 SQL> set arraysize 3 SQL> show arraysize arraysize 3

執(zhí)行以下查詢,應(yīng)該返回2行。

SQL> select c1 from test0429 where c1<='02';  C1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 01   02

其對(duì)數(shù)據(jù)塊的訪問情況如下:

ktrgtc2(): started for block <0x0007 : 0x0180414b> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0

執(zhí)行以下查詢,會(huì)返回3行。

SQL> select c1 from test0429 where c1<='03';  C1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 01   02   03

其對(duì)數(shù)據(jù)塊的訪問情況如下:

ktrgtc2(): started for block <0x0007 : 0x0180414b> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0

執(zhí)行以下查詢,會(huì)返回4行。

SQL> select c1 from test0429 where c1<='04';  C1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 01   02   03   04

其對(duì)數(shù)據(jù)塊的訪問情況如下:

ktrgtc2(): started for block <0x0007 : 0x0180414b> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0

這里之所以會(huì)出現(xiàn)對(duì)最左側(cè)葉子塊的第三次訪問。是因?yàn)楫?dāng)其返回第一行后,第二次訪問葉子塊期間,找到了3行滿足條件的記錄。由于已達(dá)到了ARRAYSIZE的限制,所以,要暫停掃描,返回結(jié)果。然后再繼續(xù)掃描葉子塊中的剩余值,看看是否仍有滿足條件的記錄。因此,會(huì)出現(xiàn)對(duì)最左側(cè)葉子塊的第三次訪問。

如果我們發(fā)出一條查詢最左側(cè)葉子塊中的最大值的SQL,又會(huì)是什么訪問情況呢?

SQL> select c1 from test0429 where c1='26';  C1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 26

我們可以看到是訪問了全部三個(gè)索引塊,并且各訪問了一次,沒有重復(fù)訪問情況的發(fā)生。

ktrgtc2(): started for block <0x0007 : 0x0180414b> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414d> objd: 0x00017ce0

之所以發(fā)生這種情況,我認(rèn)為其原因是當(dāng)其從根塊中的指針,訪問了最左側(cè)的葉子塊,找到一行滿足該條件的記錄。這時(shí),會(huì)如前所述,暫停繼續(xù)掃描,返回結(jié)果。然后繼續(xù)掃描,但由于在第一次的掃描中,已了解到了該索引條目是本索引塊中的最后一個(gè)索引條目,所以,就直接沿著最左側(cè)葉子塊上指向其后一個(gè)葉子塊的指針,訪問了位于其右側(cè)的葉子塊,即訪問了“block  <0x0007 : 0x0180414d>  ”。顯然,由于該塊中的ROW0已經(jīng)是&lsquo;27&rsquo;+254個(gè)空格了,已經(jīng)大于了條件值&lsquo;26&rsquo;,因此,結(jié)束查詢。

如果我們查詢的結(jié)果是存在于相鄰的兩個(gè)葉子塊中時(shí),其訪問情況如下:在下面的查詢中,有兩行記錄位于最左側(cè)的葉子塊中,而一行記錄位于其右側(cè)的葉子塊中。

SQL> select c1 from test0429 where c1>='25' and c1<='27';  C1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 25   26   27

其中索引塊的訪問情況如下:

ktrgtc2(): started for block <0x0007 : 0x0180414b> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414d> objd: 0x00017ce0

而當(dāng)我們查詢的結(jié)果是存在于相鄰的兩個(gè)葉子塊中,并且會(huì)湊夠ARRAYSIZE參數(shù)所指定的3行時(shí),其訪問情況會(huì)有變化。

SQL> select c1 from test0429 where c1>='25' and c1<='28';  C1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 25   26   27   28

這時(shí),我們觀察到的訪問情況如下:

ktrgtc2(): started for block <0x0007 : 0x0180414b> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414d> objd: 0x00017ce0 ktrget2(): started for block  <0x0007 : 0x0180414d> objd: 0x00017ce0

如上所示,這里之所以會(huì)對(duì)位于右側(cè)的葉子塊訪問2次,其原因是當(dāng)其訪問右側(cè)的葉子塊,并獲取到滿足條件的&lsquo;27&rsquo;和&lsquo;28&rsquo;兩條記錄時(shí),此時(shí),已經(jīng)湊夠3條了(另1條是&lsquo;26&rsquo;),所以,要暫停掃描,返回結(jié)果,然后繼續(xù)掃描。因此,這時(shí)會(huì)再次訪問右側(cè)的葉子塊。

如果換成唯一索引,其訪問行為,又會(huì)有一些差異。刪除原索引,仍在C1列上創(chuàng)建唯一索引。

SQL> drop index ind_test0429_c1;  Index dropped.  SQL> create unique index ind_unique_test0429_c1 on test0429(c1);  Index created.

查看新的唯一索引OBJECT_ID,以便查看其索引樹形結(jié)構(gòu)。

SQL> select object_id,object_name,object_type from user_objects where object_name='IND_UNIQUE_TEST0429_C1';   OBJECT_ID OBJECT_NAME                 OBJECT_TYPE ---------- ----------------------------------- -------------------      97521 IND_UNIQUE_TEST0429_C1          INDEX  SQL> alter session set events 'immediate trace name treedump level 97521';  Session altered.

如下所示,我們可以看到該結(jié)構(gòu)與此前的樹形結(jié)構(gòu)是相同的。

branch: 0x180414b 25182539 (0: nrow: 2, level: 1)    leaf: 0x180414c 25182540 (-1: nrow: 26 rrow: 26)    leaf: 0x180414d 25182541 (0: nrow: 24 rrow: 24) ----- end tree dump

再次DUMP出根塊和最左側(cè)葉子塊中的內(nèi)容,如下所示:

kdxcolev 1 KDXCOLEV Flags = - - - kdxcolok 0 kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y kdxconco 1 kdxcosdc 0 kdxconro 1 kdxcofbo 30=0x1e kdxcofeo 8049=0x1f71 kdxcoavs 8019 kdxbrlmc 25182540=0x180414c kdxbrsno 0 kdxbrbksz 8056 kdxbr2urrc 3 row#0[8049] dba: 25182541=0x180414d col 0; len 2; (2):  32 37

我們可以看到根塊中,顯示位于第二個(gè)葉子塊中的最小值的起始兩位是&lsquo;27&rsquo;,而最左側(cè)葉子塊中的內(nèi)容如下,可以看到該塊中的最大值,仍然是&lsquo;26&rsquo;+254個(gè)空格。

kdxcolev 0 KDXCOLEV Flags = - - - kdxcolok 0 kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y kdxconco 1 kdxcosdc 0 kdxconro 26 kdxcofbo 88=0x58 kdxcofeo 1116=0x45c kdxcoavs 1028 kdxlespl 0 kdxlende 0 kdxlenxt 25182541=0x180414d kdxleprv 0=0x0 kdxledsz 6 kdxlebksz 8032 row#0[7766] flag: ------, lock: 0, len=266, data:(6):  01 80 41 47 00 00 col 0; len 256; (256):  30 31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ......  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  20 20 20 20 20 20 row#1[7500] flag: ------, lock: 0, len=266, data:(6):  01 80 41 47 00 01 col 0; len 256; (256):  30 32 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ...... row#25[1116] flag: ------, lock: 0, len=266, data:(6):  01 80 41 47 00 19 col 0; len 256; (256):  32 36 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ......  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  20 20 20 20 20 20 ----- end of leaf block dump ----- End dump data blocks tsn: 7 file#: 6 minblk 16715 maxblk 16716

再次執(zhí)行只返回1行的查詢。

SQL> select c1 from test0429 where c1='01';  C1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 01

但對(duì)索引的訪問方法,已經(jīng)變?yōu)榱怂饕ㄒ粧呙瑁缦旅娴膱?zhí)行計(jì)劃所示:

SQL> select * from table(dbms_xplan.display_cursor('','','typical'));  PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SQL_ID  3kt1uqh383qbx, child number 0 ------------------------------------- select c1 from test0429 where c1='01'  Plan hash value: 3124258820  -------------------------------------------------------------------------------------------- | Id  | Operation         | Name                   | Rows  | Bytes | Cost (%CPU)| Time     | -------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT  |                        |       |       |     1 (100)|          | |*  1 |  INDEX UNIQUE SCAN| IND_UNIQUE_TEST0429_C1 |     1 |   257 |     1   (0)| 00:00:01 | --------------------------------------------------------------------------------------------  Predicate Information (identified by operation id): ---------------------------------------------------     1 - access("C1"='01')   18 rows selected.

這時(shí)觀察到的對(duì)索引塊的訪問情況如下:

ktrgtc2(): started for block <0x0007 : 0x0180414b> objd: 0x00017cf1  ktrgtc2(): started for block <0x0007 : 0x0180414c> objd: 0x00017cf1

如上圖所示,我們可以看到,并沒有發(fā)生對(duì)最左側(cè)葉子塊的兩次訪問。這是由于唯一索引的特性導(dǎo)致的。由于唯一索引中不會(huì)有重復(fù)值,所以,當(dāng)找到一行記錄,就不必再判斷是否還有其它滿足條件的記錄了。因?yàn)樵谖ㄒ凰饕?,要么沒有對(duì)應(yīng)條件值,要么就只會(huì)有一條。因此,找到一行后,就可以結(jié)束了。

如果我們對(duì)最左側(cè)葉子塊中的最大值做查詢,其結(jié)果如下:

SQL> select c1 from test0429 where c1='26';  C1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 26

如下所示,我們可以看到,仍然是訪問2個(gè)索引塊。并且,不會(huì)去訪問第二個(gè)葉子塊。

ktrgtc2(): started for block <0x0007 : 0x0180414b> objd: 0x00017cf1 ktrgtc2(): started for block <0x0007 : 0x0180414c> objd: 0x00017cf1

但是,當(dāng)執(zhí)行以下查詢時(shí),情況會(huì)發(fā)生變化。

SQL> select c1 from test0429 where c1<='04';  C1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 01   02   03   04

由于WHERE子句中不是等值比較,所以,盡管是在唯一索引上的掃描,但訪問方法又回到了索引范圍掃描的方法。如下所示:

SQL> select * from table(dbms_xplan.display_cursor('','','typical'));  PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SQL_ID  9g9p54332fyd4, child number 0 ------------------------------------- select c1 from test0429 where c1<='04'  Plan hash value: 3622766470  ------------------------------------------------------------------------------------------- | Id  | Operation        | Name                   | Rows  | Bytes | Cost (%CPU)| Time     | ------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT |                        |       |       |     2 (100)|          | |*  1 |  INDEX RANGE SCAN| IND_UNIQUE_TEST0429_C1 |     4 |  1028 |     2   (0)| 00:00:01 | -------------------------------------------------------------------------------------------  Predicate Information (identified by operation id): ---------------------------------------------------     1 - access("C1"<='04')   18 rows selected.

而且,其訪問索引塊的情況,也與此前在非唯一索引上訪問,并返回4行結(jié)果時(shí)的情形相同了。如下所示:

ktrgtc2(): started for block <0x0007 : 0x0180414b> objd: 0x00017cf1 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017cf1 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017cf1 ktrget2(): started for block  <0x0007 : 0x0180414c> objd: 0x00017cf1

“如何解決索引掃描時(shí)對(duì)同一個(gè)葉子塊訪問多次的問題”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI