暂无图片
暂无图片
4
暂无图片
暂无图片
暂无图片

Oracle SQL优化与调优之获得执行计划

原创 黄玮 2020-05-28
2899

执行计划是指示 Oracle 如何获取和过滤数据、产生最终结果集的,是影响 SQL 语句执行性能的关键因素。我们在深入了解执行计划之前,首先需要知道执行计划是在什么时候产生的,以及如何让 SQL 引擎为语句生成执行计划。

1. SQL 语句的处理过程

在深入了解执行计划之前,我们先了解 SQL 语句的处理执行过程。当一条语句提交到 Oracle 后,SQL 引擎会分为三个步骤对其处理和执行:解析(Parse)、执行(Execute)和获取(Fetch),分别由 SQL 引擎的不同组件完成。

截屏20200528 下午4.35.29.png

SQL 引擎组件
  • SQL 编译器(SQL Compiler)
    将语句编译到一个共享游标中。SQL 编译器由解析器(Parser)、查询优化器(Optimizer)和行源生成器(Row Source Generator)组成。
    o 解析器(Parser)
    执行对 SQL 语句的语法、语义分析,将查询中的视图展开、划分为小的查询块;
    o 查询优化器(Query Optimizer)
    为语句生成一组可能被使用执行计划,估算出每个执行计划的代价,并调用计划生成器(Plan Generator)生成计划,比较计划的代价,最终选择一个代价最小的计划。查询优化器由查询转换器(Query Transform)、代价估算器(Estimator)和计划生成器(Plan Generator)组成;
    注意,上述优化器实际上指的是基于代价的优化器(Cost Based Optimizer,CBO)。CBO 也是当前采用的所有优化和调优技术的核心基础。
    􏰀 查询转换器(Query Transform)决定是否重写用户的查询(包括视图合并、子查询反前套),以生成更好的查询计划;
    􏰀 代价估算器(Estimator)使用统计数据来估算操作的选择率(Selectivity)、返回数据集的势(Cardinality)和代价,并最终估算出整个执行计划的代价;
    􏰀 计划生成器(Plan Generator)会考虑可能的访问路径(Access Path)、关联方法和关联顺序,生成不同的执行计划,让查询优化器从这些计划中选择出代价最小的一个计划。
    o 行源生成器(Row Source Generator)
    行源生成器从优化器接收到优化的执行计划后,为该计划生成行源(Row Source)。行源是一个可被迭代控制的结构体,它能以迭代方式处理一组数据行、并生成一组数据行。

  • SQL 执行引擎(SQL Execution Engine)
    SQL 执行引擎依照语句的执行计划进行操作,产生查询结果。在每一个操作中,SQL 执行引擎会以迭代方式执行行源(Row Source)、生成数据行。

提示:当 Oracle 引入一些新的优化技术时,会有一些新的组件(例如:SQL 进化管理器,SPM;SQL 性能分析器,SPA 等)会与 SQL 引擎的组件融合,提供更好优化和调优方法。

我们如果想要显示一条语句的执行计划,方法有很多种。大致上分为两类:从内存或者历史数据中读取曾经执行过的语句的执行计划;使用 Explain Plan 命令解析语句后,从表 PLAN_TABLE 获得生成的执行计划。

要注意的是,如果要读取语句的执行计划,用户必须拥有语句中对象及其依赖对象的权限。如果语句中存在视图,用户必须有对视图依赖表的查询权限。例如,当一个用户 A 基于表 T 创建了一个视图 V,并将视图的查询权限赋予了用户 B,那么用户 B 仅能通过视图查询表的数据,但无法解析基于该视图的查询的执行计划。

2. 生成执行计划

在 Oracle 中,任何一条语句在解析过程中都会生成一个唯一的数值进行标识,即 SQL_ID。而同一条语句,在解析过程中,可能会因为执行环境的改变(例如某些优化参数被改变)而生成多个版本的游标,不同的游标会有不同的执行计划。每个游标都会按顺序赋予一个序列号,即 CHILD_NUMBER,一条语句生成的第一个游标的 CHILD_NUMBER 为 0;相应的,Oracle 会为每个执行计划生成一个哈希值以作区分。而多个不同版本的游标,其执行计划可能会相同,也可能不同。

因此,我们可以知道,一条合法的 SQL 语句在执行过后,在内存中最少会有一个执行计划与其游标相对应。当前实例内存(Library Cache)中的执行计划可以通过视图 V$ SQL_PLAN 读取(RAC 环境中,可以通过视图 gv$sql_plan 查看其它实例上的执行计划)。在启用了自动负载知识库(Automatic Workload Repository,AWR,10g 及以后版本),Oracle 会将内存中的执行计划存储在历史数据当中,我们可以通过查询语句或者 Oracle 提供的包 DBMS_XPLAN 从历史数据中读取;此外,从 10g 开始,Oracle 还提供一个自动优化工具 DBMS_SQLTUNE 对单个或一组语句进行自动优化,它可以在一段时间内捕捉内存中语句和执行计划来生成一组 SQL 集(或者称 SQL 调优集,SQL Tuning Set),我们同样可以从 SQL 集中读取和显示语句的执行计划;在 11g 当中,Oracle 又引入了 SQL 执行计划管理(SQL Plan Management)的特性,可以将语句的一到多个执行计划存储在一个执行计划基线(Plan Baseline)当中,我们同样可以读取基于执行计划基线生成的计划。

提示:AWR 的历史数据、执行计划基线都是有保存期限的,可以通过相关参数设置。

除了通过执行 SQL 让 Oracle 处理引擎在内存中生成执行计划外,我们还可以通过命令 Explain Plan 让优化器仅对 SQL 语句进行解释,生成查询计划。由于语句并不会实际执行,因此它可以含有没有赋值的绑定变量。

执行 Explain Plan 命令后,Oracle 会将解释生成的查询计划插入表 SYS.PLAN_TABLE$ (10G 之前,表名为 PLAN_TABLE;10G 之后,通过公共同义词 PLAN_TABLE 指向 SYS.PLAN_TABLE$)中。我们就可以通过查询语句或者 Oracle 提供的包 DBMS_XPLAN 从该表中读取查询计划。注意,通过 Explain Plan 解释出来的查询计划不会被缓存到内存中被语句执行时重用,我们在缓存当中看到的是类似“explain plan for < SQL >”的形式。

最后修改时间:2020-05-28 17:04:21
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论