Oracle 利用执行计划来避免排序操作
在oracle中,利用index来避免排序
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;
SQL> COMMIT;
SQL> SET AUTOT ON EXP
SQL> SELECT ID, NAME FROM T_NOSORT ORDER BY NAME;
----------------------------------------------------------
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 |
-------------------------------------------------------
QL> SELECT /*+ INDEX(T_NOSORT IND_T_NOSORT_NAME) */ ID, NAME FROM T_NOSORT ORDER BY NAME;
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 41 | 1230 | 827 (1)| 00:00:10 |
| 1 | TABLE ACCESS BY INDEX ROWID| T_NOSORT | 41 | 1230 | 827 (1)| 00:00:10 |
| 2 | INDEX FULL SCAN | IND_T_NOSORT_NAME | 41 | | 26 (0)| 00:00:01 |
利用索引范围扫描
SQL> SELECT ID, NAME FROM T_NOSORT WHERE NAME < 'I' ORDER BY NAME;
----------------------------------------------------------
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;
----------------------------------------------------------
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')
如果是倒序排序
QL> SELECT /*+ INDEX_DESC(T_NOSORT IND_T_NOSORT_NAME) */ ID, NAME
2 FROM T_NOSORT ORDER BY NAME DESC;
----------------------------------------------------------
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 | |
-------------------------------------------------------------------------
这里只是说明了能够避免排序的执行计划,但是不一定能提升性能
上面针对于单表
MERGE JOIN连接方式
SQL> CREATE TABLE T1 (ID NUMBER PRIMARY KEY, NAME VARCHAR2(30) NOT NULL);
SQL> CREATE TABLE T2 (ID NUMBER, NAME VARCHAR2(30));
SQL> CREATE INDEX IND_T1_NAME ON T1(NAME);
SQL> INSERT INTO T1 SELECT ROWNUM, TABLE_NAME FROM USER_TABLES;
SQL> INSERT INTO T2 SELECT ROWNUM, OBJECT_NAME FROM USER_OBJECTS;
SQL> COMMIT;
SQL> SET AUTOT ON EXP
SQL> SELECT /*+ USE_MERGE(T1, T2) */ T2.NAME, T1.ID FROM T1, T2
WHERE T1.NAME = T2.NAME ;
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 41 | 1927 | 8 (25)| 00:00:01 |
| 1 | MERGE JOIN | | 41 | 1927 | 8 (25)| 00:00:01 |
| 2 | SORT JOIN | | 41 | 1230 | 4 (25)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T1 | 41 | 1230 | 3 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 99 | 1683 | 4 (25)| 00:00:01 |
| 5 | TABLE ACCESS FULL| T2 | 99 | 1683 | 3 (0)| 00:00:01 |
----------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."NAME"="T2"."NAME")
filter("T1"."NAME"="T2"."NAME")
SQL> SELECT /*+ USE_MERGE(T2, T1) */ T2.NAME, T1.ID
FROM T1, T2 WHERE T1.NAME = T2.NAME ORDER BY T2.NAME ;
----------------------------------------------------
Plan hash value: 412793182
----------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
----------------------------------------------------
| 0 | SELECT STATEMENT | | 19 | 893 |
| 1 | MERGE JOIN | | 19 | 893 |
| 2 | SORT JOIN | | 17 | 510 |
| 3 | TABLE ACCESS FULL| T1 | 17 | 510 |
|* 4 | SORT JOIN | | 97 | 1649 |
| 5 | TABLE ACCESS FULL| T2 | 97 | 1649 |
----------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."NAME"="T2"."NAME")
filter("T1"."NAME"="T2"."NAME")
针对merge join只能对连接的列排序,且排序操作只能是升序
SQL> SELECT /*+ USE_MERGE(T2, T1) */ T2.NAME, T1.ID
FROM T1, T2 WHERE T1.NAME = T2.NAME ORDER BY T2.NAME DESC;
| 0 | SELECT STATEMENT | | 41 | 1927 | 9 (34)| 00:00:01 |
| 1 | SORT ORDER BY | | 41 | 1927 | 9 (34)| 00:00:01 |
| 2 | MERGE JOIN | | 41 | 1927 | 8 (25)| 00:00:01 |
| 3 | SORT JOIN | | 41 | 1230 | 4 (25)| 00:00:01 |
| 4 | TABLE ACCESS FULL| T1 | 41 | 1230 | 3 (0)| 00:00:01 |
|* 5 | SORT JOIN | | 99 | 1683 | 4 (25)| 00:00:01 |
| 6 | TABLE ACCESS FULL| T2 | 99 | 1683 | 3 (0)| 00:00:01 |5 - access("T1"."NAME"="T2"."NAME")
filter("T1"."NAME"="T2"."NAME")
NESTED LOOP连接
由于nested loop不会对操作结果排序,所以结果是无序的
如果驱动表在连接前是有序的,在连接后,结果还是有序的
SQL> CREATE INDEX IND_T2_ID ON T2(ID);
SQL> CREATE INDEX IND_T2_NAME ON T2(NAME);
SQL> SELECT /*+ USE_NL(T1, T2) */ T1.ID, T1.NAME, T2.NAME
2 FROM T1, T2
3 WHERE T1.ID = T2.ID
4 ;
----------------------------------------------------------
Plan hash value: 3621112097
----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost
----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 17 | 1020 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 30 |
| 2 | NESTED LOOPS | | 17 | 1020 |
| 3 | TABLE ACCESS FULL | T1 | 17 | 510 |
|* 4 | INDEX RANGE SCAN | IND_T2_ID | 1 | |
----------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."ID"="T2"."ID")
SQL> SELECT /*+ ORDERED INDEX(T1 IND_T1_NAME) USE_NL(T1, T2) */
2 T1.ID, T1.NAME, T2.NAME
3 FROM T1, T2
4 WHERE T1.ID = T2.ID
5 ORDER BY T1.NAME
6 ; ----------------------------------------------------------
Plan hash value: 1062594094
---------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
---------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 17 | 1020 |
| 1 | TABLE ACCESS BY INDEX ROWID | T2 | 1 | 30 |
| 2 | NESTED LOOPS | | 17 | 1020 |
| 3 | TABLE ACCESS BY INDEX ROWID| T1 | 17 | 510 |
| 4 | INDEX FULL SCAN | IND_T1_NAME | 17 | |
|* 5 | INDEX RANGE SCAN | IND_T2_ID | 1 | |
---------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("T1"."ID"="T2"."ID")
SQL> ALTER TABLE T2 MODIFY NAME NOT NULL;
SQL> CREATE INDEX IND_T2_NAME ON T2(NAME);
SQL> SET AUTOT OFF
SQL> UPDATE T2 SET ID = MOD(ID, 17) + 1;
SQL> COMMIT;
SQL> SET AUTOT ON EXP
SQL> SELECT /*+ ORDERED INDEX(T1 IND_T1_NAME)
2 INDEX(T2 IND_T2_NAME) USE_NL(T1, T2) */
3 T1.ID, T1.NAME, T2.NAME
4 FROM T1, T2
5 WHERE T1.ID = T2.ID
6 ORDER BY T1.NAME
7 ;
----------------------------------------------------------
Plan hash value: 3719138605
---------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
---------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 97 | 5820 |
|* 1 | TABLE ACCESS BY INDEX ROWID | T2 | 6 | 180 |
| 2 | NESTED LOOPS | | 97 | 5820 |
| 3 | TABLE ACCESS BY INDEX ROWID| T1 | 17 | 510 |
| 4 | INDEX FULL SCAN | IND_T1_NAME | 17 | |
| 5 | INDEX FULL SCAN | IND_T2_NAME | 97 | |
---------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("T1"."ID"="T2"."ID") SQL> SELECT /*+ ORDERED INDEX(T1 IND_T1_NAME)
2 INDEX_DESC(T2 IND_T2_NAME) USE_NL(T1, T2) */
3 T1.ID, T1.NAME, T2.NAME
4 FROM T1, T2
5 WHERE T1.ID = T2.ID
6 ORDER BY T1.NAME
7 ;
----------------------------------------------------------
Plan hash value: 2531946081
---------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
---------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 97 | 5820 |
|* 1 | TABLE ACCESS BY INDEX ROWID | T2 | 6 | 180 |
| 2 | NESTED LOOPS | | 97 | 5820 |
| 3 | TABLE ACCESS BY INDEX ROWID| T1 | 17 | 510 |
| 4 | INDEX FULL SCAN | IND_T1_NAME | 17 | |
| 5 | INDEX FULL SCAN DESCENDING | IND_T2_NAME | 97 | |
---------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("T1"."ID"="T2"."ID")
SQL> SELECT /*+ ORDERED INDEX(T1 IND_T1_NAME)
2 INDEX(T2 IND_T2_NAME) USE_NL(T1, T2) */
3 T1.ID, T1.NAME, T2.NAME
4 FROM T1, T2
5 WHERE T1.ID = T2.ID
6 ORDER BY T1.NAME, T2.NAME DESC
7 ; ----------------------------------------------------------
Plan hash value: 1438746903
----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 97 | 5820 |
| 1 | SORT ORDER BY | | 97 | 5820 |
|* 2 | TABLE ACCESS BY INDEX ROWID | T2 | 6 | 180 |
| 3 | NESTED LOOPS | | 97 | 5820 |
| 4 | TABLE ACCESS BY INDEX ROWID| T1 | 17 | 510 |
| 5 | INDEX FULL SCAN | IND_T1_NAME | 17 | |
| 6 | INDEX FULL SCAN | IND_T2_NAME | 97 | |
----------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("T1"."ID"="T2"."ID")
Oracle 利用执行计划来避免排序操作的更多相关文章
- Oracle sql执行计划解析
Oracle sql执行计划解析 https://blog.csdn.net/xybelieve1990/article/details/50562963 Oracle优化器 Oracle的优化器共有 ...
- 怎样看懂Oracle的执行计划
怎样看懂Oracle的执行计划 一.什么是执行计划 An explain plan is a representation of the access path that is taken when ...
- (转)Oracle定时执行计划任务
Oracle定时执行计划任务 在日常工作中,往往有些事情是需要经常重复地做的,例如每天更新业务报表.每天从数据库中提取符合条件的数据.每天将客户关系管理系统中的数据分配给员工做数据库营销……因此我们就 ...
- 【ORACLE】记录通过执行Oracle的执行计划查询SQL脚本中的效率问题
记录通过执行Oracle的执行计划查询SQL脚本中的效率问题 问题现象: STARiBOSS5.8.1R2版本中,河北对帐JOB执行时,无法生成发票对帐文件. 首先,Quartz表达式培植的启 ...
- Oracle的执行计划(来自百度文库)
如何开启oracle执行计划 http://wenku.baidu.com/view/7d1ff6bc960590c69ec37636.html怎样看懂Oracle的执行计划 http://wenku ...
- ORACLE的执行计划
转自:http://www.cnblogs.com/lovingprince/archive/2007/12/07/2166400.html 背景知识: 为了更好的进行下面的内容我们必须 ...
- oracle 理解执行计划
·BUFFER SORT是BUFFER却不是SORT 用AUTOTRACE查看执行的计划的同学常问到执行计划里的BUFFER SORT是什么意思,这里为什么要排序呢? BUFFER SORT不是一种排 ...
- 分析oracle的执行计划(explain plan)并对对sql进行优化实践
基于oracle的应用系统很多性能问题,是由应用系统sql性能低劣引起的,所以,sql的性能优化很重要,分析与优化sql的性能我们一般通过查看该sql的执行计划,本文就如何看懂执行计划,以及如何通过分 ...
- oracle sql 执行计划分析
转自http://itindex.net/detail/45962-oracle-sql-%E8%AE%A1%E5%88%92 一.首先创建表 SQL> show user USER is &q ...
随机推荐
- 关于jQuery中的offset()和position()
在jQuery中有两个获取元素位置的方法offset()和position().position()方法是在1.2.6版本之后加入的,为什么要引 入这个方法呢?这两个方法之间有什么异同?使用的时候应该 ...
- 滚动条——WPF ScrollViewer的应用
WPF ScrollViewer的应用 我们知道在一个限定高的窗体和容器中,想要把内容显示完是有些问题的,这个时候我们就要使用类似于浏览器的那个滚动条的效果了,在wpf中也同样如此,最近就碰到了这 ...
- linux上安装mysql以后root不能登录的解决办法
今天心血来潮在linux上装了mysql,装完以后用命令mysql -uroot -p登录时提示 解决办法: 使用ps aux|grep mysql 查出pid 使用kill pid结束mysql进程 ...
- 【Java】对象的创建过程
一.对象的创建过程 1.首次创建对象时或该类静态方法/静态域首次被访问时,JAVA解释器查找该类的路径,定位该类的class文件 2.载入该类的class文件,有关静态初始化的所有动作执行,但是只执行 ...
- WCF基础:绑定(一)
WCF中的终结点(ServiceEndpoint)包含有三要素:地址(EndpointAddress),绑定(Binding),契约描述(ContractDescription)三要素:其中绑定的在整 ...
- C#在winform中操作数据库,实现数据增删改查
1.前言: 运行环境:VS2013+SQL2008+Windows10 程序界面预览: 使用的主要控件:dataGridview和menuStrip等. 2.功能具体介绍: 1.首先,我们要先实现基本 ...
- LeetCode OJ:Intersection of Two Linked Lists(两个链表的插入)
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- IE6&IE7 bug
IE6 Bugs 1 .不支持用样式设置 <abbr> 元素 2 .不支持以连字符和下划线开头的 class 和 ID 名 3 . <select> 元素总是出现在堆叠最上面, ...
- JS 页面加载触发事件 document.ready和onload的区别
document.ready和onload的区别——JavaScript文档加载完成事件页面加载完成有两种事件: 一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件): 二是onlo ...
- PostgreSQL流复制记录
参考了别人的部分,添加了自己在实践中的内容,仅做记录. 1.同步流复制中 主机操作 1.1postgresql.conf wal_level = hot_standby # 这个是设置主为wal的主机 ...