很多执行计划本身就是需要排序的,通过特定的执行计划可以避免排序的产生。前两天在论坛中看到类似的问题。这里简单总结一下。
利用执行计划来避免排序操作(二):http://yangtingkun.itpub.net/post/468/243463
索引全扫描可以避免排序,相信大部分人都很清楚:
SQL> CREATE TABLE T_NOSORT (ID NUMBER PRIMARY KEY, NAME VARCHAR2(30) NOT NULL);
表已创建。
SQL> CREATE INDEX IND_T_NOSORT_NAME ON T_NOSORT(NAME);
索引已创建。
SQL> INSERT INTO T_NOSORT SELECT ROWNUM, TABLE_NAME FROM USER_TABLES;
已创建15行。
SQL> COMMIT;
提交完成。
SQL> SET AUTOT ON EXP
SQL> SELECT ID, NAME FROM T_NOSORT ORDER BY NAME;
ID NAME
---------- ------------------------------
5 BONUS
2 CHAINED_ROWS3 DEPT 1 DR$IND_T_DOCS$I
15 DR$IND_T_DOCS$K
14 DR$IND_T_DOCS$N
9 DR$IND_T_DOCS$R
7 DUMMY
4 EMP
6 SALGRADE
8 T
12 T_DUMP
13 T_IOT
10 T_NOSORT
11 T_OTHER
已选择15行。
执行计划
----------------------------------------------------------
Plan hash value: 1041838668
-------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
-------------------------------------------------------
| 0 | SELECT STATEMENT | | 15 | 450 |
| 1 | SORT ORDER BY | | 15 | 450 |
| 2 | TABLE ACCESS FULL| T_NOSORT | 15 | 450 |
-------------------------------------------------------
SQL> SELECT /*+ INDEX(T_NOSORT IND_T_NOSORT_NAME) */ ID, NAME FROM T_NOSORT ORDER BY NAME;
ID NAME
---------- ------------------------------
5 BONUS
2 CHAINED_ROWS3 DEPT 1 DR$IND_T_DOCS$I
15 DR$IND_T_DOCS$K
14 DR$IND_T_DOCS$N
9 DR$IND_T_DOCS$R
7 DUMMY
4 EMP
6 SALGRADE
8 T
12 T_DUMP
13 T_IOT
10 T_NOSORT
11 T_OTHER
已选择15行。
执行计划
----------------------------------------------------------
Plan hash value: 3156728236
------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 15 | 450 |
| 1 | TABLE ACCESS BY INDEX ROWID| T_NOSORT | 15 | 450 |
| 2 | INDEX FULL SCAN | IND_T_NOSORT_NAME| 15 | |
------------------------------------------------------------------------
同样的道理,索引范围扫描也是可以避免排序的:
SQL> SELECT ID, NAME FROM T_NOSORT WHERE NAME < 'I' ORDER BY NAME;
ID NAME
---------- ------------------------------
5 BONUS
2 CHAINED_ROWS3 DEPT 1 DR$IND_T_DOCS$I
15 DR$IND_T_DOCS$K
14 DR$IND_T_DOCS$N
9 DR$IND_T_DOCS$R
7 DUMMY
4 EMP
已选择9行。
执行计划
----------------------------------------------------------
Plan hash value: 1041838668
-------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
-------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 270 |
| 1 | SORT ORDER BY | | 9 | 270 |
|* 2 | TABLE ACCESS FULL| T_NOSORT | 9 | 270 |
-------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("NAME"<'I')
SQL> SELECT /*+ INDEX(T_NOSORT IND_T_NOSORT_NAME) */ ID, NAME
2 FROM T_NOSORT WHERE NAME < 'I' ORDER BY NAME;
ID NAME
---------- ------------------------------
5 BONUS
2 CHAINED_ROWS3 DEPT 1 DR$IND_T_DOCS$I
15 DR$IND_T_DOCS$K
14 DR$IND_T_DOCS$N
9 DR$IND_T_DOCS$R
7 DUMMY
4 EMP
已选择9行。
执行计划
----------------------------------------------------------
Plan hash value: 919790285
-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 270 |
| 1 | TABLE ACCESS BY INDEX ROWID| T_NOSORT | 9 | 270 |
|* 2 | INDEX RANGE SCAN | IND_T_NOSORT_NAME | 9 | |
-------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("NAME"<'I')
filter("NAME"<'I')
对于上面的排序,如果是倒序排列,那么可以选择INDEX_DESC扫描来避免排序:
SQL> SELECT /*+ INDEX_DESC(T_NOSORT IND_T_NOSORT_NAME) */ ID, NAME
2 FROM T_NOSORT ORDER BY NAME DESC;
ID NAME
---------- ------------------------------
11 T_OTHER
10 T_NOSORT
13 T_IOT
12 T_DUMP
8 T
6 SALGRADE
4 EMP
7 DUMMY
9 DR$IND_T_DOCS$R
14 DR$IND_T_DOCS$N
15 DR$IND_T_DOCS$K
1 DR$IND_T_DOCS$I
3 DEPT 2 CHAINED_ROWS
5 BONUS
已选择15行。
执行计划
----------------------------------------------------------
Plan hash value: 2858378269
-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 15 | 450 |
| 1 | TABLE ACCESS BY INDEX ROWID| T_NOSORT | 15 | 450 |
| 2 | INDEX FULL SCAN DESCENDING| IND_T_NOSORT_NAME | 15 | |
-------------------------------------------------------------------------
同样的原理还应用于索引组织表之中,按照索引组织表的主键排序和上面描述的索引排序没有什么区别。
这里需要强调一点,这里只是列举能够避免排序的执行计划,并非意味着避免了排序就一定会带来性能的提升,如果为了避免排序而选择了不恰当的执行计划,那么代价可能会比执行排序操作的代价要大得多。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/25230815/viewspace-1044533/ ,如需转载,请注明出处,否则将追究法律责任。