Posted on 2009-07-21 21:04
Prayer 閱讀(372)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
數(shù)據(jù)庫(kù),SQL 、
DB2
1)索引唯一掃描 如果查詢時(shí)是通過(guò)unique或primary key約束來(lái)保證只返回一條數(shù)據(jù),那么優(yōu)化器就會(huì)選擇索引唯一掃描,這是訪問(wèn)一條數(shù)據(jù)的最快方式。
2)索引范圍掃描
索引鍵非唯一,當(dāng)遇到如下條件時(shí)會(huì)使用索引范圍掃描:
1.col=:b1
2.col<:b1
3.col>:b1
3)索引降序范圍掃描
與2)中的情況相同,只不過(guò)2)默認(rèn)是安裝升序進(jìn)行查找的,而這里是按降序進(jìn)行查找,如:
select line_item_id,order_id from order_items where order_id<:b1 order by order_id desc;
4)跳躍式索引(Skip Scan Index)。當(dāng)表有一個(gè)復(fù)合索引,而在查詢中有除了索引中第一列的其他列作為條件,并且優(yōu)化器模式為CBO,這時(shí)候查詢計(jì)劃就有可能使用到SS,另外通過(guò)使用提示index_ss(CBO下)來(lái)強(qiáng)制使用SS。跳躍式索引使復(fù)合索引從邏輯上分為幾個(gè)小的子索引,分的條件就是復(fù)合索引列的第一個(gè)字段,可以這樣理解,Oracle將索引從邏輯上劃分為a.num_distinct個(gè)子索引,每次對(duì)一個(gè)子索引進(jìn)行掃描。因此SS的索引掃描成本為a.num_distinct.而且使用SS的條件需要第一列的distinct num要足夠小
5)index full scan和Index Fast Full Scan(全索引掃描和快速全索引掃描)
index full scan和index fast full scan是指同樣的東西嗎?答案是no。兩者雖然從字面上看起來(lái)差不多,但是實(shí)現(xiàn)的機(jī)制完全不同。我們一起來(lái)看看兩者的區(qū)別在哪里?
首先來(lái)看一下IFS,FFS能用在哪里:在一句sql中,如果我們想搜索的列都包含在索引里面的話,那么index full scan 和 index fast full scan 都可以被采用代替full table scan。比如以下語(yǔ)句:
SQL> CREATE TABLE TEST AS SELECT * FROM dba_objects WHERE 0=1;
SQL> CREATE INDEX ind_test_id ON TEST(object_id);
SQL> INSERT INTO TEST
SELECT *
FROM dba_objects
WHERE object_id IS NOT NULL AND object_id > 10000
ORDER BY object_id DESC;
17837 rows created.
SQL> analyze table test compute statistics for table for all columns for all indexes;
Table analyzed.
SQL> set autotrace trace;
SQL> select object_id from test;
17837 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=CHOOSE (Cost=68 Card=17837 Bytes=71348)
1 0 TABLE ACCESS (FULL) OF 'TEST' (Cost=68 Card=17837 Bytes=71348)
這時(shí)候Oracle會(huì)選擇全表掃描,因?yàn)?object_id 列默認(rèn)是可以為null的,來(lái)修改成 not null:
SQL>alter table test modify(object_id not null);
SQL> select object_id from test;
17837 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=CHOOSE (Cost=11 Card=17837 Bytes=71348)
1 0 INDEX (FAST FULL SCAN) OF 'IND_TEST_ID' (NON-UNIQUE) (Cost=11 Card=17837 Bytes=71348)
當(dāng)然我們也可以使用index full scan:
SQL> select/*+ index(test ind_TEST_ID)*/ object_id from test;
17837 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=CHOOSE (Cost=41 Card=17837 Bytes=71348)
1 0 INDEX (FULL SCAN) OF 'IND_TEST_ID' (NON-UNIQUE) (Cost=101 Card=17837 Bytes=71348)
我們看到了兩者都可以在這種情況下使用,那么他們有什么區(qū)別呢?有個(gè)地方可以看出兩者的區(qū)別, 來(lái)看一下兩者的輸出結(jié)果,為了讓大家看清楚一點(diǎn),我們只取10行。
INDEX FAST FULL SCAN
SQL> select object_id from test where rownum<11;
OBJECT_ID
----------
66266
66267
66268
66269
66270
66271
66272
66273
66274
66275
10 rows selected.
INDEX FULL SCAN
SQL> select/*+ index(test ind_TEST_ID)*/ object_id from test where rownum<11;
OBJECT_ID
----------
10616
12177
12178
12179
12301
13495
13536
13539
13923
16503
10 rows selected.
可以看到兩者的結(jié)果完全不一樣,這是為什么呢?這是因?yàn)楫?dāng)進(jìn)行index full scan的時(shí)候oracle定位到索引的root block,然后到branch block(如果有的話),再定位到第一個(gè)leaf block, 然后根據(jù)leaf block的雙向鏈表順序讀取。它所讀取的塊都是有順序的,也是經(jīng)過(guò)排序的。
而index fast full scan則不同,它是從段頭開(kāi)始,讀取包含位圖塊,root block,所有的branch block, leaf block,讀取的順序完全有物理存儲(chǔ)位置決定,并采取多塊讀,沒(méi)次讀取db_file_multiblock_read_count個(gè)塊。
使用這兩種索引掃描需要表的索引字段至少有一個(gè)是not null限制。
快速全索引掃描比普通索引掃描速度快是因?yàn)榭焖偎饕龗呙枘軌蚨鄩K讀取,并且能并行處理。
普通快速索引掃描可以減少排序操作。
6)Index Join索引連接
我們都知道表與表之間可以連接,那么索引與索引之間呢?當(dāng)然也可以。索引連接是一種索引之間的hash連接,當(dāng)查找的字段都已經(jīng)包括在索引中時(shí),就不需要去訪問(wèn)表的內(nèi)容,直接通過(guò)訪問(wèn)多個(gè)索引就能得到結(jié)果。Index join只能在CBO使用的情況下進(jìn)行。