order by 使用索引的情況

order by 使用索引的情況
參考http://pub.itpub.net/post/26/2862?SelectActiveLayout=a
1)默認情況是按順序先取rownum,再order by
2)如果order by 滿足使用索引的情況,則先order by,再取rownum
order by 使用索引是有條件的:
1)ORDER BY中所有的列必須包含在相同的索引中並保持在索引中的排列順序.
2)ORDER BY中所有的列必須定義爲非空.
3)另外,如果ORDER BY中的列在where 條件中出現,也會使用索引

問題:
id爲PK

select a,b,id from adf where rownum<7
A B ID
---------------------- ---------------------- ------
0 a 1
0 d 2
0 c 333
0 b 4
0 a 5
1 a 66
6 rows selected

select a,b,id from adf where rownum<7 order by id
A B ID
---------------------- ---------------------- ------
0 a 1
0 d 2
0 b 4
0 a 5
1 b 7
1 c 8
6 rows selected
結果是先order by ,再執行rownum<7

但如果是這樣:
select a,b,id from adf where rownum<7 order by b
A B ID
---------------------- ---------------------- ------
0 a 1
0 a 5
1 a 66
0 b 4
0 c 333
0 d 2
6 rows selected
結果是先執行rownum<7,再order by

這是爲什麼???
難道是因爲id是PK,所以就不同。

~~~~~~~~~~~~~~~~~~~~~~
解答:
跟主健及其上面的索引有關係:

ID是主健.

SQL> select * from t;

ID ID1
---------- ----------
1 2
2 4
4 3


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'T'

SQL> select * from t where rownum<3 order by id desc;

ID ID1
---------- ----------
4 3
2 4


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 COUNT (STOPKEY)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T'
3 2 INDEX (FULL SCAN DESCENDING) OF 'PK' (UNIQUE)
'因爲是主健,先進行索引的排序全表掃描,然後在 count 2'

SQL> select * from t where rownum<3 order by id1;

ID ID1
---------- ----------
1 2
2 4


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (ORDER BY)
2 1 COUNT (STOPKEY)
3 2 TABLE ACCESS (FULL) OF 'T'
'沒有使用索引,先進行全表掃描,然後再count 2,再排序'

爲什麼會使用pk的索引呢?一般的索引行嗎?
我們看看:

1)在id1上創建索引


SQL> create index id1idx on t(id1);

索引已創建。
SQL> select * from t where rownum<3 order by id1;

ID ID1
---------- ----------
1 2
2 4


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (ORDER BY)
2 1 COUNT (STOPKEY)
3 2 TABLE ACCESS (FULL) OF 'T' '還是全表掃描'

SQL> select * from t where id1>0 and rownum<3 order by id1;
'加了id1>0 ,這樣會使用到id1的索引'

ID ID1
---------- ----------
1 2
4 3


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 COUNT (STOPKEY)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T'
3 2 INDEX (RANGE SCAN) OF 'ID1IDX' (NON-UNIQUE)


2)pk的索引是因爲有order by 而使用的。order by 使用索引是有條件的:
ORDER BY中所有的列必須包含在相同的索引中並保持在索引中的排列順序.
ORDER BY中所有的列必須定義爲非空.

因爲id1是可以爲空的,所以order by 不會使用它。而pk的索引是非空的,所以order by 會使用。

我們將id1設爲非空看看。


SQL> alter table t
2 modify (id1 int not null);

表已更改。

SQL> select * from t where rownum<3 order by id1;

ID ID1
---------- ----------
1 2
4 3


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 COUNT (STOPKEY)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T'
3 2 INDEX (FULL SCAN) OF 'ID1IDX' (NON-UNIQUE)
'這次,order by id1 使用了id1上的索引!'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章