《Oracle高性能SQL引擎剖析:SQL优化与调优机制详解》一1.2 显示执行计划

简介: 本节书摘来自华章出版社《Oracle高性能SQL引擎剖析:SQL优化与调优机制详解》一 书中的第1章,第1.2节,作者:黄玮,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

1.2 显示执行计划

我们现在知道,有三个途径可以获取查询计划:v$sql_plan、dba_hist_sql_plan和PLAN_TABLE。如果需要读取一条SQL语句的执行计划,就需要知道该条语句的SQL_ID,如果该语句存在多个游标或者执行计划,则还需要知道游标的CHILD_NUMBER或计划的哈希值(可选)。而无论我们通过哪个途径来获取执行计划,显示方式主要是两种:语句查询和包DBMS_XPLAN显示。

1.2.1 通过查询语句显示计划

通过查询语句从一些视图里读出执行计划并作格式化输出的方法都非常相似,这里以v$sql_plan视图为例,示例程序见代码清单1-1。
代码清单1-1 显示执行计划(查询语句)

HELLODBA.COM>col "Query Plan_Table" format a30

-- 提示:SQL_ID可以从视图v$sql_text和dba_hist_sqltext(或stats$sqltext)等视图中查询获得。

HELLODBA.COM>select id,lpad(' ', 2*(level-1))||operation||' '||options||' '||
  2         object_name||' '||decode(id, 0, 'Cost='||cost) "Query Plan_Table"
  3  from v$sql_plan
  4  start with id = 0
  5         and sql_id = 'dq7gjn1yrpcyz'
  6         and plan_hash_value = 616708042
  7  connect by prior id = parent_id
  8         and sql_id = 'dq7gjn1yrpcyz'
  9         and plan_hash_value = 616708042;

        ID Query Plan_Table
---------- ------------------------------
         0 SELECT STATEMENT   Cost=2
         1   TABLE ACCESS FULL T_USERS

1.2.2 通过包DBMS_XPLAN显示计划

这个包可以根据我们选择的函数以及输入的参数来格式化显示相关的执行计划,在我们随后的内容中,主要会使用(也推荐读者使用)该工具显示执行计划。
DBMS_XPLAN含有5个函数用于输出格式化的执行计划,display、display_cursor、display_awr、display_sqlset和display_sql_plan_baseline,分别用于显示Explain Plan命令解释的计划、内存中的执行计划、AWR历史数据中的计划、SQL优化集中语句的计划、执行计划基线(关于SQL优化集和执行计划基线,我们会在后面第7章中具体介绍)。它们都是管道化表函数(Pipelined Table Function),返回的结果是一个系统自定义的集合数据类型dbms_xplan_type_table。我们可以通过表函数(Table)进行映射后进行查询。

1.2.2.1 DISPLAY

DISPLAY函数用于显示存储在PLAN_TABLE中的执行计划,或与PLAN_TABLE拥有相同结构的表中的执行计划。此外,如果从视图v$sql_plan_statistics_all可以获得该执行计划的相关统计数据,DISPLAY也可以格式化输出这些数据。
参数描述:
q TABLE_NAME:存储查询计划的表名(不区分大小写),默认值为PLAN_TABLE。
q STATEMENT_ID:SQL语句ID。在PLAN_TABLE中,每条语句的执行计划都会有一个唯一的ID来标识。这个ID可以在执行Explain Plan命令时,通过Set Statement_id子句来指定。如果输入为NULL,则会获取最近一条被解释的语句。
q FORMAT:输出格式。在DISPLAY函数中,有以下预定义的格式(模板)可供选择:
m 'BASIC':基本格式。输出的内容最少,仅仅输出查询计划中每个操作的ID、名称和选项以及操作的对象名。
m 'TYPICAL':典型格式。输出的内容是我们进行语句调优时大多数情况下所需要的信息。除了基本格式中的内容外,还会输出优化器估算出的每个操作的记录行数、字节数、代价和时间,以及相关的提示信息(如远程SQL、优化器建议等)。如果存在谓词(Predicate)条件,还会输出每个操作中的过滤(Filter)条件和访问(Access)条件。此外,如果查询涉及分区表,还会输出分区裁剪信息;如果查询涉及并行查询,还会输出并行操作的相关信息(如表队列信息、并行查询分布方式等)。这种格式是默认格式。
m 'SERIAL':串行执行格式。这种格式和典型格式的输出内容基本一致,不同之处在于,对并行查询,它不会输出相关的并行内容。
m 'ALL':完全格式。输出的内容相对完整。除了典型格式的内容以外,还会输出字段投射信息和别名信息。
除了这些预定义的格式外,用户还可以通过在格式化字符串中添加或者屏蔽一些关键词进行细化输出。每一个细化选项代表了输出内容中的单个信息(可能是执行计划表中的一个列,也可能是一个附加信息)。在DISPLAY函数中,以下细化控制选项可供选择:
m ROWS:优化器估算出的记录行数;
m BYTES:优化器估算出的字节数;
m COST:优化器估算出的代价;
m PARTITION:分区裁剪;
m PARALLEL:并行查询;
m PREDICATE:谓词;
m PROJECTION:字段投射;
m ALIAS:别名;
m REMOTE:分布式查询信息;
m NOTE:相关注释信息。
细化控制选项和预定格式一起使用。例如,如果你希望输出基本格式内容,并输出优化器估算出的记录行数,可以用“BASIC ROWS”作为格式字符串;而如果希望输出典型格式,但不要其中的谓词条件,则可以输入“TYPICAL -PREDICATE”作为格式字符串,即在希望被屏蔽信息的对应控制选项前加上“-”。
q FILTER_PREDS:该参数接收合法的谓词过滤条件(可以是谓词逻辑表达式,也可以包含子查询),以过滤从查询计划表中读取的内容。例如,可以输入“COST > 10”以限制输出所有估算代价大于10的操作。
示例见代码清单1-2。
代码清单1-2 显示执行计划(DISPLAY函数)

HELLODBA.COM>explain plan for select * from t_users where user_id=:A;
Explained.
HELLODBA.COM>select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------
Plan hash value: 371495088

------------------------------------------------------------------------------------------
| Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            |     1 |    86 |     1   (0)| 00:00:02 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T_USERS    |     1 |    86 |     1   (0)| 00:00:02 |
|*  2 |   INDEX UNIQUE SCAN         | T_USERS_PK |     1 |       |     1   (0)| 00:00:02 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("USER_ID"=TO_NUMBER(:A))

14 rows selected.

HELLODBA.COM>select * from table(dbms_xplan.display(null,null,'BASIC ROWS BYTES'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------
Plan hash value: 371495088

------------------------------------------------------------------
| Id  | Operation                   | Name       | Rows  | Bytes |
------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            |     1 |    86 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T_USERS    |     1 |    86 |
|   2 |   INDEX UNIQUE SCAN         | T_USERS_PK |     1 |       |
------------------------------------------------------------------

1.2.2.2 DISPLAY_CURSOR

DISPLAY_CURSOR函数可以显示内存中一个或者多个游标的执行计划。同样,可以通过输入参数限定SQL、游标以及输出格式。
用户必须对视图V$SQLV、$SQL_PLAN和V$SQL_PLAN_STATISTICS_ALL的SELECT有权限,才能正常调用DISPLAY_CURSOR函数。
参数描述:
q SQL_ID:所显示执行计划的SQL语句的ID。该ID可以从V$SQL.SQL_ID、V$SESSION.SQL_ID或者V$SESSION.PREV_SQL_ID获得。如果没有指定SQL_ID(指定NULL),则默认会显示当前会话中最后一条执行的SQL语句。
q CURSOR_CHILD_NO:语句的子游标序号。我们知道,受到执行环境的影响,一条SQL语句可能会产生多个版本的子游标,每个子游标都会与一个执行计划相映射(多个子游标也可能映射同一个执行计划)。通过CURSOR_CHILD_NO可以限制仅显示某一个子游标的执行计划。如果不指定该参数,则会显示该语句的所有子游标的执行计划。
q FORMAT:格式化控制字符串。DISPLAY函数的格式化控制字符串的所有选项都适用于DISPLAY_CURSOR函数。由于运行语句还可以通过提示GATHER_PLAN_STATISTICS或设置系统参数STATISTICS_LEVEL为“ALL”收集语句运行的性能统计数据,因此在细化选项中还有额外的选项,以选择是否输出这些数据。
m IOSTATS:是否输出计划的输入输出(IO)统计数据;
m MEMSTATS:在启用了PGA自动管理(参数pga_aggregate_target的值大于0)的情况下,是否输出计划的输入内存统计数据(操作的内存使用量、内存读次数等);
m ALLSTATS:包含了IOSTATS和MEMSTATS的全部内容;
m LAST:以上三个选项输出的统计数据都是实际产生的数据,而非估算数据,它们是该游标所有执行所产生的数据的总和。你可以增加LAST选项以限定仅显示最后一次运行的统计数据。

 此外,还有一些未公布的选项可用于该函数的输出控制。首先是预定义格式:

m 'ADVANCED':高级格式。高级格式除了会输出完全格式中的所有内容外,还会视情况输出绑定变量窥视信息和计划概要(Outline)信息;
m OUTLINE:是否以提示(HINT)的方式显示计划概要;
m PEEKED_BINDS:是否显示绑定变量窥视信息;
m BUFFSTATS:是否显示内存读次数(包括一致性读和当前读次数),该信息为IOSTATS的一部分;
m PLAN_HASH:是否显示计划的哈希值,该选项同样适用于DISPLAY函数。
示例见代码清单1-3。
screenshot

1.2.2.3 DISPLAY_AWR

DISPLAY_AWR函数显示存储在AWR历史数据的执行计划。
提示:要正常调用DISPLAY_AWR参数,必须对以下视图有权限:DBA_HIST_SQL_PLAN和DBA_HIST_SQLTEXT的SELECT。
参数描述:
q SQL_ID:所显示执行计划的SQL语句的ID。该ID可以从DBA_HIST_SQL_PLAN.SQL_ID或DBA_HIST_SQLTEXT.SQL_ID获得,该参数必须指定非空值,没有默认值;
q PLAN_HASH_VALUE:执行计划的哈希值。我们之前提到,每个执行计划都有一个哈希值。通过该值,可以显示SQL语句的特定执行计划。如果该参数未指定或为NULL,则会显示语句的所有执行计划;
q DB_ID:指定显示哪个数据库的执行计划,默认为本地数据库ID;
提示:我们可以将其他数据库的AWR数据导入本地数据库进行分析。
q FORMAT:格式化控制字符串。与DISPLAY的相同选项类似。
示例见代码清单1-4。
screenshot

1.2.2.4 DISPLAY_SQLSET

DISPLAY_SQLSET函数显示存储在一个SQL调优集中的语句的执行计划。
提示:DBMS_SQLTUNE是Oracle 10g中提供的一个自动调优的工具包,它可以对单条语句进行调优,也可以对一组SQL集进行调优,我们在后面章节会做详细介绍。
参数描述:
q SQLSET_NAME:SQL集的名称。每个SQL集都有一个单独的名称(可以是创建时用户指定的,也可以是系统自动生成的),我们需要指定从哪个SQL集中读取和显示语句的执行计划,该参数没有默认值,必须指定;
q SQL_ID:所显示执行计划的SQL语句的ID。该ID可以从USER/DBA/ALL_SQLSET_PLANS.SQL_ID获得,该参数必须指定非空值,没有默认值;
q PLAN_HASH_VALUE:执行计划的哈希值。如果未指定或为NULL,则会显示语句的所有执行计划;
q FORMAT:格式化控制字符串。与DISPLAY的FORMAT选项相同;
q SQLSET_OWNER:SQL集的所有者,默认为当前用户名。
示例见代码清单1-5。
screenshot

1.2.2.5 DISPLAY_SQL_PLAN_BASELINE

DISPLAY_SQL_PLAN_BASELINE函数显示存储在数据字典当中SQL执行计划基线的计划。
提示:SQL执行计划管理是Oracle 11g中提供的一个新特性,用于管理SQL语句的一组执行计划(执行计划基线,Plan Baseline),保证语句运行性能稳定性。
参数描述:
q SQL_HANDLE:执行计划基线所属SQL的句柄名称,它由Oracle在创建或载入执行计划到基线当中时自动生成,可以通过视图dba_sql_plan_baselines查询,默认为NULL;
q PLAN_NAME:执行计划基线中某个执行计划的名称,它由Oracle在创建或载入执行计划到基线当中时自动生成,可以通过视图dba_sql_plan_baselines查询,默认为NULL;
q FORMAT:格式化控制字符串。DISPLAY_SQLSET函数的格式化选项与DISPLAY的选项相同。
当SQL_HANDLE和PLAN_NAME都为空时,显示所有基线数据中的全部执行计划。
示例见代码清单1-6。
screenshot
screenshot

1.2.3 AUTOTRACE

AUTOTRACE是Oracle自带的客户端工具SQLPlus的一个特性。启用AUTOTRACE后,SQLPLus会自动收集执行过的语句的执行计划、性能统计数据等,并在语句执行结束后显示在SQL*Plus中。
要使用AUTOTRACE,需要先做以下准备,用DBA用户创建角色PLUSTRCE,并将该角色赋予用户:
HELLODBA.COM>conn sys/sys as sysdba
Connected.

HELLODBA.COM>@?/SQLPLUS/ADMIN/PLUSTRCE.SQL
HELLODBA.COM>grant plustrace to demo;
Grant succeeded.
在执行语句之前,在SQL*Plus中打开AUTOTRACE。可以在打开AUTOTRACE时选择不同选项,以控制输出的内容。选项如下所示:
q SET AUTOTRACE ON:打开AUTOTRACE,并输出所有内容,包括语句本身的查询结果、执行计划,以及性能统计数据。
q SET AUTOTRACE ON EXPLAIN:打开AUTOTRACE,并输出语句本身的查询结果和执行计划,不输出性能统计数据。
q SET AUTOTRACE ON STATISTICS:打开AUTOTRACE,并输出语句本身的查询结果和性能统计数据,不输出执行计划。
q SET AUTOTRACE TRACE:打开AUTOTRACE,并输出执行计划和性能统计数据,不输出语句本身的查询结果。
q SET AUTOTRACE TRACE EXPLAIN:打开AUTOTRACE,并输出执行计划,不输出语句本身的查询结果和性能统计数据。
q SET AUTOTRACE TRACE STATISTICS:打开AUTOTRACE,并输出性能统计数据,不输出语句本身的查询结果和执行计划。
q SET AUTOTRACE OFF:关闭AUTOTRACE。
一个完整的AUTOTRACE报告输出包括三个部分:第一部分为SQL本身的执行结果;第二部分为SQL的执行计划;第三部分为SQL实际执行的性能统计数据。由于执行计划和执行的性能数据都是进行SQL调优时的重要参考信息,因此AUTOTRACE是进行SQL语句性能调优的一个非常实用的辅助方法。
提示:当打开AUTOTRACE后,在执行语句之前,Oracle会调用EXPLAIN PLAN命令对语句进行解析;在执行完成后,从PLAN_TABLE中查询和显示执行计划。因此,由于受到共享游标、绑定变量窥视等设置的影响,这一执行计划可能会与实际执行计划不同。

1.2.4 其他方法

除了上述方法外,我们还可以通过其他一些途径获取到语句的执行计划。但在这些方法所产生的数据里,执行计划通常仅是辅助我们解决问题的一个部分,而非重点。

1.2.4.1 SQL_TRACE(或者10046跟踪事件)

SQL_TRACE跟踪的内容由三个部分组成:执行语句时造成的等待事件(Waits)、执行语句时产生的性能统计数据,以及语句的执行计划和绑定变量信息。这里仅介绍执行计划相关部分。
在会话或者系统中启动SQL跟踪后,会话结束或者关闭SQL跟踪之前,会话(或系统)中所有运行的语句的性能统计数据都会记录到UDUMP目录(user_dump_dest参数指定)下一个跟踪文件中(未指定标识字符串tracefile_identifier的情况下,文件名格式为_ORA_.trc),从跟踪文件中,我们可以找到语句的执行计划。示例见代码清单1-7。
screenshot
screenshot

1.2.4.2 OPTIMIZER_TRACE(或者10053跟踪事件)

OPTIMIZER_TRACE可以跟踪优化器生成语句执行计划的整个过程,并且,在11g中还可以通过设置事件来指定仅跟踪一个或多个组件的信息。同样,其跟踪内容都会写入UDMP目录下的一个跟踪文件中,文件的命名方式和SQL_TRACE产生的跟踪文件的命名方式相同。示例见代码清单1-8。
screenshot

相关文章
|
4天前
|
SQL 存储 Oracle
Oracle的PL/SQL定义变量和常量:数据的稳定与灵动
【4月更文挑战第19天】在Oracle PL/SQL中,变量和常量扮演着数据存储的关键角色。变量是可变的“魔术盒”,用于存储程序运行时的动态数据,通过`DECLARE`定义,可在循环和条件判断中体现其灵活性。常量则是不可变的“固定牌”,一旦设定值便保持不变,用`CONSTANT`声明,提供程序稳定性和易维护性。通过 `%TYPE`、`NOT NULL`等特性,可以更高效地管理和控制变量与常量,提升代码质量。善用两者,能优化PL/SQL程序的结构和性能。
|
24天前
|
SQL 存储 关系型数据库
一文搞懂SQL优化——如何高效添加数据
**SQL优化关键点:** 1. **批量插入**提高效率,一次性建议不超过500条。 2. **手动事务**减少开销,多条插入语句用一个事务。 3. **主键顺序插入**避免页分裂,提升性能。 4. **使用`LOAD DATA INFILE`**大批量导入快速。 5. **避免主键乱序**,减少不必要的磁盘操作。 6. **选择合适主键类型**,避免UUID或长主键导致的性能问题。 7. **避免主键修改**,保持索引稳定。 这些技巧能优化数据库操作,提升系统性能。
219 4
一文搞懂SQL优化——如何高效添加数据
|
1天前
|
SQL 分布式计算 资源调度
一文解析 ODPS SQL 任务优化方法原理
本文重点尝试从ODPS SQL的逻辑执行计划和Logview中的执行计划出发,分析日常数据研发过程中各种优化方法背后的原理,覆盖了部分调优方法的分析,从知道怎么优化,到为什么这样优化,以及还能怎样优化。
|
4天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标属性:数据的“导航仪”与“仪表盘”
【4月更文挑战第19天】Oracle PL/SQL游标属性如同车辆的导航仪和仪表盘,提供丰富信息和控制。 `%FOUND`和`%NOTFOUND`指示数据读取状态,`%ROWCOUNT`记录处理行数,`%ISOPEN`显示游标状态。还有`%BULK_ROWCOUNT`和`%BULK_EXCEPTIONS`增强处理灵活性。通过实例展示了如何在数据处理中利用这些属性监控和控制流程,提高效率和准确性。掌握游标属性是提升数据处理能力的关键。
|
4天前
|
SQL XML 前端开发
sql 性能优化基于explain调优(二)
sql 性能优化基于explain调优(二)
11 0
|
4天前
|
SQL Oracle 安全
Oracle的PL/SQL循环语句:数据的“旋转木马”与“无限之旅”
【4月更文挑战第19天】Oracle PL/SQL中的循环语句(LOOP、EXIT WHEN、FOR、WHILE)是处理数据的关键工具,用于批量操作、报表生成和复杂业务逻辑。LOOP提供无限循环,可通过EXIT WHEN设定退出条件;FOR循环适用于固定次数迭代,WHILE循环基于条件判断执行。有效使用循环能提高效率,但需注意避免无限循环和优化大数据处理性能。掌握循环语句,将使数据处理更加高效和便捷。
|
4天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL条件控制:数据的“红绿灯”与“分岔路”
【4月更文挑战第19天】在Oracle PL/SQL中,IF语句与CASE语句扮演着数据流程控制的关键角色。IF语句如红绿灯,依据条件决定程序执行路径;ELSE和ELSIF提供多分支逻辑。CASE语句则是分岔路,按表达式值选择执行路径。这些条件控制语句在数据验证、错误处理和业务逻辑中不可或缺,通过巧妙运用能实现高效程序逻辑,保障数据正确流转,支持企业业务发展。理解并熟练掌握这些语句的使用是成为合格数据管理员的重要一环。
|
4天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL表达式:数据的魔法公式
【4月更文挑战第19天】探索Oracle PL/SQL表达式,体验数据的魔法公式。表达式结合常量、变量、运算符和函数,用于数据运算与转换。算术运算符处理数值计算,比较运算符执行数据比较,内置函数如TO_CHAR、ROUND和SUBSTR提供多样化操作。条件表达式如CASE和NULLIF实现灵活逻辑判断。广泛应用于SQL查询和PL/SQL程序,助你驾驭数据,揭示其背后的规律与秘密,成为数据魔法师。
|
8天前
|
SQL 关系型数据库 数据库
【后端面经】【数据库与MySQL】SQL优化:如何发现SQL中的问题?
【4月更文挑战第12天】数据库优化涉及硬件升级、操作系统调整、服务器/引擎优化和SQL优化。SQL优化目标是减少磁盘IO和内存/CPU消耗。`EXPLAIN`命令用于检查SQL执行计划,关注`type`、`possible_keys`、`key`、`rows`和`filtered`字段。设计索引时考虑外键、频繁出现在`where`、`order by`和关联查询中的列,以及区分度高的列。大数据表改结构需谨慎,可能需要停机、低峰期变更或新建表。面试中应准备SQL优化案例,如覆盖索引、优化`order by`、`count`和索引提示。优化分页查询时避免大偏移量,可利用上一批的最大ID进行限制。
33 3
|
25天前
|
SQL 关系型数据库 MySQL
【MySQL技术之旅】(7)总结和盘点优化方案系列之常用SQL的优化
【MySQL技术之旅】(7)总结和盘点优化方案系列之常用SQL的优化
39 1

推荐镜像

更多