看懂执行计划(生成、查看、理解Oracle的执行计划)
下面是好好范文网小编收集整理的看懂执行计划(生成、查看、理解Oracle的执行计划),仅供参考,欢迎大家阅读!
SQL是如何被执行的
SQL语句只是定义了要查询什么样的数据,但是没有定义数据是怎样被查询出来。
接下来这棵生成的语法树会被送到DB的基于开销的优化器(Cost-Based Optimizer, CBO),优化器会创建执行计划(Execution Plan),并通过选择join类型(Nested Loops, Merge Join, Hash Join等)、join顺序、是否使用索引、使用什么索引等方式找到使用开销(CPU, IO, 内存)最小的计划作为最佳的执行计划。
然后这个最佳的执行计划被送到DB的执行器(Executor),执行器执行这个计划,并将取到的数据返回给DB调用方。
什么是执行计划
A statement's execution plan is the sequence of operations Oracle performs to run the statement. The EXPLAIN
PLAN
statement displays execution plans chosen by the Oracle optimizer for SELECT
, UPDATE
, INSERT
, and DELETE
statements.
执行计划是DB优化器生成的,为了完成一个SQL查询的一系列必要且有序的数据库操作(Operation)的集合。
生成执行计划
预估执行计划:每执行一次EXPLAIN PLAN,DB优化器(Optimizer)就会生成执行计划而不执行SQL(因此叫“预估”),并写入PLAN_TABLE表中(Oracle默认使用PLAN_TABLE临时表来保存EXPLAIN PLAN的结果):
The PLAN_TABLE
is automatically created as a global temporary table to hold the output of an EXPLAIN
PLAN
statement for all users. PLAN_TABLE
is the default sample output table into which the EXPLAIN
PLAN
statement inserts rows describing execution plans
EXPLAIN PLAN SET STATEMENT_ID = 'statement1' --指定该条语句的statement_id,后续可用于查询PLAN_TABLE表中的执行计划 INTO my_plan_table --可以不使用默认的PLAN_TABLE而使用自定义表FORSELECT last_name FROM employees; --要分析的SQL语句。INSERT, UPDATE, SELECT和DELETE语句。
实际执行计划:在SQL执行的时候由DB优化器(Optimizer)创建的执行计划。
EXPLAIN PLAN的执行结果代表在EXPLAIN这条SQL的时候,DB应该如何去执行这条SQL。而实际在执行的时候可能由于数据数量,结构(例如增加了索引等)等的变化,使得实际的执行计划与预估执行计划略有不同。
查询执行计划
预估执行计划
--不带选项SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());--这里使用了自定义的表my_plan_table和自定义的SQL ID statement1SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY('my_plan_table','statement1','TYPICAL'));
执行结果大概长这样:
实际执行计划
由于实际执行计划要在执行SQL时才会生成,查看执行计划前,要先执行SQL。
--不带选项,直接查询最后一条SQL的执行计划SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());--指定了sql_id和child_number,查询指定SQL的执行计划。SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('gwp663cqh5qbf',0));-------------------------------------------------------------1.为了区别其他的SQL,需要在执行SQL的时候加入特殊标记的注释,比如:SELECT /* TOTO */ ename, dname FROM dept d join emp e USING (deptno);--2.通过SQL标记,查到sql_id和child_number。v$sql是一个系统视图,保存执行过的sql语句SELECT sql_id, child_number FROM v$sql WHERE sql_text LIKE '%TOTO%';SQL_ID CHILD_NUMBER---------- -----------------------------gwp663cqh5qbf 0--3.再查询该SQL的执行计划SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('gwp663cqh5qbf',0));
执行结果大概长这样:
理解执行计划
Oracle的执行计划看起来是以tab符和行的方式展示的,实际上它是一棵执行树,因此在阅读执行计划的时候,要从树的叶子节点看起,即从执行计划表里Operation列缩进最多的一行看起。
假如有以下SQL:
SELECT ename FROM emp e, dept d WHERE e.deptno = d.deptno AND e.empno=7369;
执行之后查询实际执行计划:
SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR());
结果:
可以看到,执行计划包含三部分:执行计划的hash值,以表格展示的执行计划树,以及Predicate信息。
对于这个执行计划,ID=2和ID=3这两行的缩进最多,应该从这两行开始看(注意:表格的ID列中有*的行,代表该行在Predicate Information部分有更详细信息):
ID=3,这是一个全表扫描DEPT的操作,有4行记录共12字节。
ID=2,全表扫描EMP表,有1行记录共13字节。在Predicate Information中看到,这个步骤还要过滤掉empno=7369的信息,而这正是sql中的where条件。
ID=1,两个表进行hash join,得到1行记录共16字节。在Predicate Information中看到,这个步骤join的方式是e.deptno=d.deptno,这也是sql种的where条件。
ID=0,执行SELECT操作,获取结果。
很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、高并发、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家。点击领取资料