查询执行计划所需的权限

这里的执行计划是指游标中的实际执行计划。

 

执行计划简介

执行计划就是Oracle基于成本(Cost)、算法和统计信息,最终得到资源消耗最低的SQL执行步骤的组合。其中,成本的值是一个估算值,包括访问路径、关联方式、I/O、CPU和内存等。

执行计划操作本身无法区分经过良好调整的语句和执行欠佳的语句。

该计划由一系列步骤组成。 每个步骤要么从数据库中物理检索数据行,要么为发出语句的用户准备它们。 以下计划显示了员工表和部门表的联接:

row source tree(行源树)是执行计划的核心。 该树显示以下信息:

除了行源树之外,计划表还包含以下信息:

About PLAN_TABLE

PLAN_TABLE 是默认示例输出表,EXPLAIN PLAN 语句将在其中插入用于描述执行计划的行

Oracle 数据库自动在 SYS 模式中,创建全局临时表 PLAN_TABLE$,并创建 PLAN_TABLE 作为同义词。 PLAN_TABLE 的所有必要权限均授予 PUBLIC。 因此,每个会话都会在其临时表空间中获得自己的 PLAN_TABLE 私有副本。

您可以使用 SQL 脚本 catplan.sql 手动创建全局临时表和 PLAN_TABLE 同义词。 该脚本的名称和位置取决于您的操作系统。 在 UNIX 和 Linux 上,该脚本位于 $ORACLE_HOME/rdbms/admin 目录中。 例如,启动 SQL*Plus 会话,使用 SYSDBA 权限连接,然后运行脚本,如下所示:

示例输出表 PLAN_TABLE 的定义,可在分发介质上的 SQL 脚本中找到。 您的输出表必须具有与此表相同的列名称和数据类型。 该脚本的通用名称是 utlxplan.sql。 确切的名称和位置取决于您的操作系统。

 

方法1:EXPLAIN PLAN

EXPLAIN PLAN 语句显示优化器为 SELECTUPDATEINSERTDELETE 语句选择的执行计划。

EXPLAIN PLAN 的输出显示,在解析 SQL 语句时,数据库将如何运行该 SQL 语句。 由于执行环境和解释计划环境的差异,解释计划可能与语句执行期间使用的实际计划不同

当发出 EXPLAIN PLAN 语句时,优化器选择一个执行计划,然后将描述执行计划每个步骤的行,插入到指定的计划表PLAN TABLE中。 您还可以发出 EXPLAIN PLAN 语句,作为 SQL 跟踪工具的一部分。

EXPLAIN PLAN 语句是 DML 语句,而不是 DDL 语句。 因此,Oracle 数据库不会隐式提交 EXPLAIN PLAN 语句所做的更改

语法格式

 

除了可以使用dbms_xplan.display读取plan_table中最新的内容,还可以使用以下内置脚本:

DBMS_XPLAN.DISPLAY table function

此函数接受用于显示计划表输出的选项。 您可以指定:

使用 DBMS_XPLAN 显示 PLAN_TABLE 输出的示例包括:

建立plan_table表

手动查询plan_table内容

在 EXPLAIN PLAN 中指定语句 ID:示例

对于多个语句,您可以指定语句标识符并使用它来标识您的特定执行计划。

在使用 SET STATEMENT ID 之前,请删除该语句 ID 的任何现有行。 在以下示例中,st1 被指定为语句标识符。

Example 6-1 Using EXPLAIN PLAN with the STATEMENT ID Clause

删除指定的执行计划数据

 

为 EXPLAIN PLAN 输出指定不同位置:示例

EXPLAIN PLANINTO 子句指定一个不同的表来存储输出。

如果您不想使用名称 PLAN_TABLE,请在运行 catplan.sql 脚本后创建一个新的同义词。 例如:

以下语句将输出定向到 my_plan_table

使用 INTO 子句时可以指定语句 ID,如以下语句所示:

 

方法2:SET AUTOTRACE

SQL*Plus 中的 AUTOTRACE 命令生成执行计划和有关查询性能的统计信息。 该命令提供磁盘读取和内存读取等统计信息。 请参阅 SQL*Plus 用户指南和参考。

注意:默认情况只有sys用户有权限

 

方法3:statistics_level=all

 

方法4:DBMS_XPLAN.DISPLAY_CURSOR

DBMS_XPLAN.DISPLAY

使用dbms_xplan.display读取plan_table中最新的内容

此函数接受用于显示计划表输出的选项。 您可以指定:

DBMS_XPLAN.DISPLAY_CURSOR

用于获取内存中shared_pool游标缓存。

查询内存中的执行计划(也叫游标执行计划),即已经执行过的SQL语句的执行计划。

 

DBMS_XPLAN.DISPLAY_AWR

用于获取AWR基表WRH$_SQL_PLAN

 

方法5:AWR SQL report

AWR SQL report 使用的脚本为 $ORACLE_HOME/rdbms/admin/awrsqrpt.sqlawrsqrpi.sql。通常使用的脚本为 awrsqrpt.sql,该脚本可生成 SQL 在 AWR 信息内保存的执行计划等信息。而 awrsqrpi.sql 可以配合 awr 信息的导出与导入的功能,在被导入的库中生成相关的 AWR 报告。导入与导出的脚本同样在如上的路径里,为 awrextr、awrload,本次不进行演示。

报告会生成在当前目录中。

与 AWR 报告采集相同,因为性能数据的记录是累计的值,所以两个 snap_id 间如果重启过数据库会报错。如果在选择的 snap_id 间没有该条 SQL 的信息同样会报错。

通常会用于问题诊断时对问题 SQL 的总体概况进行了解,因为可以查看 SQL 的多个执行计划及各执行计划的执行统计信息。

优势:可以在报告中查看执行计划的执行统计信息;

劣势:需要生成报告;缺少执行计划的谓词信息;需要权限较高。

 

方法6:10046 trace

查看10046产生的trc文件名和路径的方法

  1. show parameter USER_DUMP_DEST显示trc文件存储的路径 -> 查找对应当前session的trc文件(若当前是单用户,则是最新产生的文件)。

  2. 如果是使用ordebug产生trc文件,可以用oradebug tracefile_name得到trc文件名和路径。

 

方法7:PLSQL-DEV

按F5

 

其他方法:sqlhc

和 explain plan for 一样的还可以使用 PL/SQL developer 工具的 F5 键也可查看执行计划,SQL Monitor 工具也可以查看,当然更高级的 sqlhc 工具,这里顺便说说 sqlhc 工具,这个工具收集的信息非常全面,值得大家尝试。

上传 sqlhc 文件,公众号后台回复【sqlhc】获取,输入 T 和 sqlid 即可生成。sqlhc 是 SQL health check的简称,能够收集sql相关的表、索引、统计信息、优化器参数、SQL执行情况、等待事件等信息,可以帮你检查SQL存在的问题并优化 SQL。

有可能更长或者更短(根据 AWR 保存周期、字典表大小不同相差较大,一般系统应该在 5 分钟以内能够完成),对数据库没有影响。执行过程有 log,也有屏显。执行过程会 insert 数据到 plan_table 表,执行结束会 rollback。

结束后生成的文件名以 sqlhc 开头,依次是日期、时间、sql_id。类似这样:sqlhc_20211125_1810_9a4tv1dduu9u4.zip

其中 4 个 html 文件和 log.zip 是通常存在的。

10053 trace 文件的生成需要 11.2 版本以上,sql_id 仍在 library cache 内的情况下。

如果 sql_monitor.zip 也包含在 sqlhc 压缩包内,说明你的 SQL 执行时间超过了 5s,或者是并行的 SQL,而且收集 sqlhc 时仍保留在 sql monitor 的内存。sql monitor 对分析 sql 执行计划有很大帮助,如果遇到问题收集 sqlhc 信息及时,就非常有可能收集到 sql monitor 文件。如果一个 sql 执行完后超过半小时没有收集 sqlhc,sql monitor 信息就就非常有可能被刷出内存。

主要分析的的 3 个 html 文件是:

 

 

如何选择方法

选择时一般遵循以下规则:

  1. 如果 sql 执行很长时间才出结果或返回不了结果,用方法1:explain plan for

  2. 跟踪某条 sql 最简单的方法是方法1:explain plan for,其次是方法2:set autotrace on

  3. 如果相关查询某个 sql 多个执行计划的情况,只能用方法4:dbms_xplan.display_cursor 或方法6:awrsqrpt.sql

  4. 如果 sql 中含有函数,函数中有含有 sql,即存在多层调用,想准确分析只能用方法5:10046 追踪

  5. 想法看到真实的执行计划,不能用方法1:explain plan for 和方法 2:set autotrace on

  6. 想要获取表被访问的次数,只能用方法 3:statistics_level = all

 

获取真实消耗资源

执行计划是SQL语句执行前基于当前的统计信息生成的,日中rows、bytes、cost、time等为评估值,为了获取更为准确的实际值,即A_ROWS,A_TIME等,数据库在执行SQL语句时需要做额外的收集。

 

常用的执行计划查看语句

 

示例

查询预计的执行计划,尚未执行

查询已经执行过的sql语句的执行计划

示例 20-8 文字导致不同的执行计划

Example 20-9 Bind Variables Result in Cursor Reuse

查询从游标缓存中获取计划信息:

使用提示来收集运行时信息:

 

SQL监控报告

DBMS_XPLAN 'ALLSTATS LAST' 不会在执行查询时为您提供运行时统计信息的连续视图,但 SQL Monitor 解决了这个问题。 它需要 Oracle Tuning Pack,因此请务必检查您的数据库版本的许可证用户指南。 该工具对于生成计划和监控 SQL 非常有用,并且可以通过 Performance Hub 中的 Enterprise Manager 来使用。 在我介绍这一点之前,您也可以在命令行上使用它(这一事实经常由于某种原因被错过或忘记):

下载

SQL_ID 参数是可选的,但我通常会显式设置它,因为系统中可能有多个长时间运行的查询,因此默认报告有时会选取与我正在试验的 SQL 语句不同的 SQL 语句。 数据库自动使长时间运行的查询可供 SQL Monitor 使用,但在本例中我使用了 MONITOR 提示,因为查询非常快并且通常不会显示。 在查询执行时对其进行监视非常有用,因为您可以观察其进度并从中学习。 这就是 SQL Monitor 真正有用的地方,因为您可以在另一个会话中观察查询并查看其统计信息不断更新。 您不一定要等待它完成才能确定查询的哪一部分花费了很长时间,因此有时可以避免等待完成。 请注意,您可以在执行查询时获取“ALL +OUTLINE”计划详细信息 - 只需使用上面的示例 B。 您甚至可以使用命令行生成活动的 HTML 报告! 这是捕获 SQL 执行计划并稍后以交互方式探索它的好方法。 只需像这样运行报告:

注意:浏览器需要 Internet 访问,因为 HTML 报告会下载一些外部资源。

执行计划解析

前置概念

数据访问路径

索引唯一扫描

通过唯一索引查找一个数值经常返回单个ROWID,如果存在unique或primary key约束,oracle经常实现唯一性扫描。

索引范围扫描

使用一个索引存取多行数据,在唯一索引上使用索引范围扫描的典型情况是:在谓词(where限制条件)中使用了范围操作符。

在非唯一索引上都使用索引范围扫描。使用index range scan的3种情况:

  1. 在唯一索引列上使用了范围操作符

  2. 在组合索引上,只使用了部分列进行查询,导致查询出多行

  3. 对非唯一索引列上进行的任何查询

索引全扫描

与全表扫描对应,也有相应的索引全扫描,而且此时查询出的数据都必须从索引种可以直接得到。

索引快速扫描

扫描索引中的所有数据块,但与index full scan不同的是,其不对查询结果进行排序,即数据不是以排序顺序被返回。在这种方法中,可以使用多块读功能,也可以使用并行读取,以便获得最大吞吐量和缩短执行时间。

表连接

排序合并连接(sort merge join,SMJ).

本质上是嵌套循环连接的变体。

  1. 首先生成row source1所需的数据,然后对这些数据按照连接操作关联列(例如 A.col3)进行排序

  2. 随后生成row source2所需的数据,然后对这些数据按照与sort source1对应的连接操作关联列(例如 B.col4)进行排序

  3. 最后两边已排序的行被放在一起执行合并操作,即将2个row source按照连接条件连接起来。

嵌套循环连接(nested loops,NL)

此连接方法有驱动表(外部表)的概念,其实,该连接过程就是一个2层嵌套循环,因此外层循环的次数越少越好,这也是为什么将小表或返回较少row source的表作为驱动表(用于外层循环)的理论依据。但是该理论只是一般指导原则,因为遵循这个理论并不能总保证使该语句产生的IO次数最少。有时不遵循该理论反而会获得更好的效率。如果使用这种连接方法,那么决定使用哪个表作为驱动表就很重要。

哈希连接(hash join,HJ)

哈希连接在oracle7.3以后引入,从理论上来说比NL和SMJ都更高效,而且只用在CBO优化器中。

较小的row source被用来构建hash table与bitmap,第二个row source被用来被hansed,并与第一个row source生成的hash table进行匹配,以便进行进一步的连接。bitmap被用来作为一种比较快的查找方法,来检查在hash table中是否有匹配的行。特别的,当hash table比较大而不能全部放在内存中时,这种查找方法更为有用。这种连接方法也有NL连接中所谓的驱动表的概念,被构建为hash table与bitmap的表作为驱动表,当被构建的hash table和bitmap可以被容纳在内存中时,这种连接方法效率极高

笛卡尔积连接

两个row source做连接,但是它们之间没有关联条件时,就会在两个row source中做笛卡尔乘积,这通常应该是误操作(忘记写连接条件)。

笛卡尔积是一个表的每一行一次与另一个表中的所有行匹配。在特殊情况下可以使用笛卡尔积连接,比如星形连接。

hints提示

不要乱用hints,因为oracle有时基于CBO的计划看似不是最优的计划,但在CBO模式下会被oracle认为有可能就是最优的执行计划。

开发者在没有得到充分的SQL执行计划和相关统计信息时,请勿使用hints

优化器提示

表连接提示

索引提示

并行提示

访问路径提示

执行优先级

右上原则

最右,最上先执行

树形图解法

Pasted image 20221027091659

理解执行计划