一、如何查看SQL语句的执行计划
1、在SQL*PLUS环境中
执行SET AUTOTRACE ON 可以打开启动自动跟踪功能,如下(下面的红色字体是敲入的命令): ChenZw> set autotrace onChenZw> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO———- ———- ——— ———- ————– ———- ———- ———- 7369 SMITH CLERK 7902 17-12月-80 800 20 7499 ALLEN SALESMAN 7698 20-2月 -81 1600 300 30 7521 WARD SALESMAN 7698 22-2月 -81 1250 500 30 7566 JONES MANAGER 7839 02-4月 -81 2975 20 7654 MARTIN SALESMAN 7698 28-9月 -81 1250 1400 30 7698 BLAKE MANAGER 7839 01-5月 -81 2850 30 7782 CLARK MANAGER 7839 09-6月 -81 2450 10 7788 SCOTT ANALYST 7566 19-4月 -87 3000 20 7839 KING PRESIDENT 17-11月-81 5000 10 7844 TURNER SALESMAN 7698 08-9月 -81 1500 0 30 7876 ADAMS CLERK 7788 23-5月 -87 1100 20 7900 JAMES CLERK 7698 03-12月-81 950 30 7902 FORD ANALYST 7566 03-12月-81 3000 20 7934 MILLER CLERK 7782 23-1月 -82 1300 10
已选择14行。
执行计划———————————————————-Plan hash value: 3956160932
————————————————————————–| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |————————————————————————–| 0 | SELECT STATEMENT | | 14 | 518 | 3 (0)| 00:00:01 || 1 | TABLE ACCESS FULL| EMP | 14 | 518 | 3 (0)| 00:00:01 |————————————————————————–
统计信息———————————————————- 476 recursive calls 0 db block gets 90 consistent gets 9 physical reads 0 redo size 1423 bytes sent via SQL*Net to client 416 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 7 sorts (memory) 0 sorts (disk) 14 rows processed 如同 ChenZw> set linesize 200ChenZw>
2、在PL/SQL Developer软件中
在PL/SQL Developer窗口中,点击“文件”的“新建”菜单中选择“SQL窗口”,在里面输入自己要执行的SQL,例如上面的 SELECT * FROM EMP; 然后点击“F5”按钮,系统会自动弹出“解释计划窗口”,并且将该SQL的执行计划在“解释计划窗口”中显示出来 或者直接创建“解释计划窗口”也可以进入解释计划窗口。 现在回过头来看这个SQL语句,使用的是“ ChenZw> select t.rowid,t.* from emp t;
ROWID EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO —————— —– —— ————- ————— —– —— AAAQ+jAAEAAAAAeAAA 7369 SMITH CLERK 7902 17-12月-80 800 20 AAAQ+jAAEAAAAAeAAB 7499 ALLEN SALESMAN 7698 20-2月 -81 1600 300 30 AAAQ+jAAEAAAAAeAAC 7521 WARD SALESMAN 7698 22-2月 -81 1250 500 30 AAAQ+jAAEAAAAAeAAD 7566 JONES MANAGER 7839 02-4月 -81 2975 20 AAAQ+jAAEAAAAAeAAE 7654 MARTIN SALESMAN 7698 28-9月 -81 1250 1400 30 AAAQ+jAAEAAAAAeAAF 7698 BLAKE MANAGER 7839 01-5月 -81 2850 30 AAAQ+jAAEAAAAAeAAG 7782 CLARK MANAGER 7839 09-6月 -81 2450 10 AAAQ+jAAEAAAAAeAAH 7788 SCOTT ANALYST 7566 19-4月 -87 3000 20 AAAQ+jAAEAAAAAeAAI 7839 KING PRESIDENT 17-11月-81 5000 10 AAAQ+jAAEAAAAAeAAJ 7844 TURNER SALESMAN 7698 08-9月 -81 1500 0 30 AAAQ+jAAEAAAAAeAAK 7876 ADAMS CLERK 7788 23-5月 -87 1100 20 AAAQ+jAAEAAAAAeAAL 7900 JAMES CLERK 7698 03-12月-81 950 30 AAAQ+jAAEAAAAAeAAM 7902 FORD ANALYST 7566 03-12月-81 3000 20 AAAQ+jAAEAAAAAeAAN 7934 MILLER CLERK 7782 23-1月 -82 1300 10
index unique scan 索引唯一扫描,当可以优化器发现某个查询条件可以利用到主键、唯一键、具有外键约束的列,或者只是访问其中某行索引所在的数据的时候,优化器会选择这种扫描类型。
第二种: index range scan 索引范围扫描,当优化器发现在 index full scan 全索引扫描,如果要查询的数据可以全部从索引中获取,则使用全索引扫描。
第四种: index fast full scan 索引快速扫描,扫描索引中的全部的数据块,与全索引扫描的方式基本上类似。两者之间的明显的区别是,索引快速扫描对查询的数据不进行排序,数据返回的时候不是排序的。“在这种存取方法中,可以使用多块读功能,也可以使用并行读入,从而得到最大的吞吐量和缩短执行时间”。
三、几种常见的索引类型的模拟
创建测试表以及测试数据的SQL:
USERID NUMBER(20), NAME VARCHAR2(20), DEPTNO NUMBER(20));–模拟数据BEGIN FOR I IN 0..1000 LOOP INSERT INTO TBL VALUES( I,CONCAT(‘TBL’,I),MOD(I,2)); END LOOP;END;
SELECT * FROM TBL;
1) ChenZw> select rowid,tbl.* from tbl where rownum<10;
ROWID USERID NAME DEPTNO—————— ———- ——————– ———-AAAUhAAAEAAAAIcAAA 796 TBL796 0AAAUhAAAEAAAAIcAAB 797 TBL797 1AAAUhAAAEAAAAIcAAC 798 TBL798 0AAAUhAAAEAAAAIcAAD 799 TBL799 1AAAUhAAAEAAAAIcAAE 800 TBL800 0AAAUhAAAEAAAAIcAAF 801 TBL801 1AAAUhAAAEAAAAIcAAG 802 TBL802 0AAAUhAAAEAAAAIcAAH 803 TBL803 1AAAUhAAAEAAAAIcAAI 804 TBL804 0
然后带着rowid去查询,看这个时候的执行计划: ChenZw> select * from tbl where rowid = ‘AAAUhAAAEAAAAIcAAA’; 执行计划———————————————————-Plan hash value: 2623095911
———————————————————————————–| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |———————————————————————————–| 0 | SELECT STATEMENT | | 1 | 50 | 1 (0)| 00:00:01 || 1 | TABLE ACCESS BY USER ROWID| TBL | 1 | 50 | 1 (0)| 00:00:01 |———————————————————————————– 上面的TABLE ACCESS BY USER ROWID是一种效率最高的获取数据的方法。
2) index unique scan 修改上面的表,增加一个主键,等于自动会增加一个唯一键约束: ALTER TABLE TBL ADD CONSTRAINT TBLID PRIMARY KEY (USERID); 执行下面的SQL语句: ChenZw> select * from tbl where userid = 100; 执行计划———————————————————-Plan hash value: 1167568666
————————————————————————————-| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |————————————————————————————-| 0 | SELECT STATEMENT | | 1 | 38 | 2 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| TBL | 1 | 38 | 2 (0)| 00:00:01 ||* 2 | INDEX UNIQUE SCAN | TBLID | 1 | | 1 (0)| 00:00:01 |————————————————————————————-
从上面的执行计划可以看出,优化器首先是根据为刚才建立的索引TBLID来找到100的ROWID,然后根据ROWID去找到100所在的行数据。
2) index full scan 为上面的表增加一个联合索引,在TBL.NAME和TBL.DEPTNO两个列上,SQL如下: CREATE INDEX INDEX_TBL_NAME_DEPTNO ON TBL(NAME,DEPTNO);
3) index range scan 执行下面的语句: ChenZw> select * from tbl where userid between 10 and 100;已选择91行。执行计划———————————————————-Plan hash value: 2314926374
————————————————
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!