热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

执行计划2:查看更多的信息

在Part1中,使用了两种获取执行计划的方法,来证明对同一条存在绑定变量的语句可以生成两种截然不同的执行计划。Part2中我们会评估几种查看真实执行计划的方法,但先关注目前接触到函


译者  林锦森 · 沃趣科技数据库技术专家

出品  沃趣科技


Part 1中我们了解了两种获取执行计划的方式,第一种是优化器预测它将会怎么执行,通过以下方法查询获取:

explain plan for {sql statement}
select * from table(dbms_xplan.display);

第二种是优化器在我们执行语句后真正的执行路径,通过以下方法查询获取:

set serveroutput off
{sql statement}
select * from table(dbms_xplan.display_cursor);

事实上,在Part 1中,我故意使用两种获取执行计划的方法,来证明对同一条存在绑定变量的语句可以生成两种截然不同的执行计划。

Part 2中我们会评估几种查看真实执行计划的方法,但是首先我们关注目前我们接触到函数的其他调用选项,这会使我们对执行计划在最终用户的环境中的复现更加自信。

Format Options


一般来说,如果想要执行计划与最终用户环境一致的话,我们需要他们生产数据的备份,对应的统计信息,系统的参数还有一致的输入。生产数据以及统计信息一般都是一样的,所以我们真正需要关注的就是客户环境是否不同以及语句输入;我们可以通过数据库来帮助我们获取在某一刻的执行信息。
这里也有一个小提醒,需要注意数据、统计信息还有谓词条件的及时同步。举个例子,如果你的生产数据是好几个星期前的,那么你执行语句时要根据几个星期前用户当时执行的语句去执行;因为如果条件中存在SYSDATE,那么就不能很好的模拟当时的环境。
Part 1中提到过的,调用dbms_xplan.display_cursor()可以赋值三个参数,它们分别是sql_idchild_numberformatting option有两个formatting option参数能有效的帮助你解决最近一次出现的问题,"peeked_binds""outline"前者会列出(只需要一点运气)优化查询时使用的真实的值,后者会提供一个hint的列表,如果我们为了这个查询创建了一个存储大纲或者SQL Plan Baseline,通过这些hint我们可以发现优化器的环境是否不同。
这里有个小例子,通过对视图dba_extentscopy表的查询来演示使用和输出。

alter session setworkarea_size_policy = manual;
alter session setsort_area_size = 10485760;

alter session setoptimizer_mode = first_rows_10;
alter session set"_hash_join_enabled" = false;

set serveroutput off

variable m_owner varchar2(32)
variable m_object varchar2(32)
execute :m_owner :='TEST_USER'
execute :m_object := 'T1'

select /*+ tracking */ * from t1 
where owner = :m_owner 
and segment_name =:m_object 
order by extent_id;

select * from table(
dbms_xplan.display_cursor(null,null,'outlinepeeked_binds')
);

我修改了一些优化器相关的参数,set serveroutput off不会导致dbms_xplan.display_cursor()输出关于dbms_output.get_lines()的调用,可以在查询时通过定义的一组参数使用绑定变量。之后我调用display_cursor(null, null, 'outlinepeeked_binds')来展示我最近的查询并且添加可用的绑定变量的值到Outline/SQL Pan Management信息中。这是输出结果:

SQL_ID  0wwbn4bhvrrxj, child number 0
-------------------------------------
select /*+ tracking */  * from t1 where owner = :m_owner and
segment_name = :m_object order by extent_id

Plan hash value3684778271

--------------------------------------------------------------------------------------
Id  | Operation                    | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |       |       |       |     3 (100)|          |
|   1 |  SORT ORDER BY               |       |     1 |    65 |     3  (34)| 00:00:01 |
|*  2 |   TABLE ACCESS BY INDEX ROWID| T1    |     1 |    65 |     2   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | T1_I2 |     2 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Outline Data
-------------
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
      DB_VERSION('11.2.0.4')
      FIRST_ROWS(10)
      OUTLINE_LEAF(@"SEL$1")
      INDEX_RS_ASC(@"SEL$1" "T1"@"SEL$1" ("T1"."SEGMENT_NAME"))
      END_OUTLINE_DATA
  */


Peeked Binds (identified by position):
--------------------------------------
   1 - :M_OWNER (VARCHAR2(30), CSID=178): 'TEST_USER'
   2 - :M_OBJECT (VARCHAR2(30), CSID=178): 'T1'

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("OWNER"=:M_OWNER)
   3 - access("SEGMENT_NAME"=:M_OBJECT)

这个例子中,我们很幸运的获得了优化器在执行计划信息中记录的所有绑定变量的值,包括CSID(charcater set id)这种细节,当你开使用NLS字符集时,有时候会造成一些意外。
我们先看”Outline Data”,可以看到hint “first_rows(10)”是唯一被记录的我们会话的变更,剩下的变更都没有被捕捉到;format option也给了我们一个提示,我们可以在这个查询开始试验时需要做一些额外的检查,来确认我们能否获得一个更好的计划。这次我们假设其他人已经执行过这个查询了,在我们分析前,我们需要根据一些特殊的文本来追踪(这就是我为什么在语句中添加/*+ tracking */,这个实际上不是hint)

column sql_id new_valuem_sql_id
column child_number new_valuem_child_no

select  sql_id,child_number, sql_text 
from   v$sql 
where   sql_textlike '%tracking%' 
and    sql_text not like '%v$sql%'
;

select * from table(
dbms_xplan.display_cursor('&m_sql_id',&m_child_no,'outlinepeeked_binds')
);

select 
namevalue 
from 
v$sql_optimizer_env 
where 
sql_id      = '&m_sql_id' 
and child_number =&m_child_no 
and isdefault   = 'NO'
;

这些代码都能在SQL*PLUS里执行,我已经设置了一些列定义用来捕捉这个查询语句上次返回的值,SQL_IDCHILD_NUMBER的值是我们所需要的。在这里我假设这条语句仅仅只有一个子游标。就像你看到的,我使用'&替换'将获取到的值带入到display_cursor()的调用与v$sql_optimizer_env的查询中。这里不显示对display_cursor()的调用结果(输出结果与前面的重复),只显示对v$sql_optimizer_env的查询结果。

NAME                                    VALUE
-----------------------------------------------------------------
hash_area_size                          20971520
sort_area_size                          10485760
optimizer_mode                          first_rows_10
_hash_join_enabled                      false
workarea_size_policy                    manual
_smm_auto_cost_enabled                  false

v$sql_optimizer_env视图保存了优化器环境的参数,这些参数在优化每一个子游标时都是生效的。我选择了那些没有默认值,可以看到Oracle输出了6个参数,其中4个是我们设置的,还有两个:hash_area_size_smm_auto_cost_enabledhash_area_size如果没有明确的设置过,它会等于两倍的sort_area_size,当我们将workarea_size_policy设置为manual时,_smm_auto_cost_enabled参数也会自动的设置为false11.2.0.4中有330个优化器参数(12.1.0.1中增加至415个,这也是为什么很难从二手信息中获取到给定查询到执行路径原因之一),其中50个参数是非隐藏参数,其余的大部分都是隐藏参数,只有在改变他们的默认值时才会展示在查询结果里。
我在简单的提下另一个formatting 选项 "advanced',奇怪的是他会给我们比"all'选项更多的信息。如果你仅仅想看执行查询时内存里所有的信息,那么你可以调用display_cursor({sql_id},{child_number},’all’)(如果有许多子游标,可以将child_number值设为NULL,则会输出所有的语句)之后如果需要解决问题时我们还会继续学习更多formatting选项,不过目前我们要暂时先放下,来看看一些可以"事后"从生产系统获取执行计划的选项。如果想获得更多可用的选项,可以查看$ORACLE_HOME/rdbms/admin/dbmsxpln.sql.

AWR and Statspack


如果一个查询属于"资源密集型"的,那么他会出现在statspackAWR里,并且它的执行计划以及一些统计会保存在资源库里。OEM(Grid ControlCloud Control)中有关于AWR的图形化界面,$ORACLE_HOME/rdbms/admin中有statspackAWRSQL接口。statspack的脚本为sprepsql.sqlAWR的为awrsqrpt.sql
如果你对于用命令行生成AWR或者statspack很熟悉,那么除了需要SQL_ID(AWR)或者"old hashvalues"(statspack)以外,几乎都是一样的。报告会给你语句的全文,一些执行统计信息,在指定期间所有不同的执行计划,还有不同计划进入和离开library cache的时间表。这个计划不会输出绑定值,outline information,甚至谓词信息,就是很基础的执行计划还有一些性能的统计。AWR在这方面比statspack好,因为它分别聚合了不同执行计划的统计数据,所以更容易比较不同的执行计划。
另一个AWR的优点是你可以通过调用dbms_xplan.display_awr()获取AWR里历史的执行计划。这个调用需要4个参数,SQL_IDplan_hash_valuedatabase idformat optino最简单的调用就是只给定SQL_ID的值,结果会输出AWR中保存的所有这条SQL的执行计划,你也可以选择输出你想要的执行计划。就像调用dbms_xplan.display_cursor() 一样,你也可以得到outline information和优化器使用的绑定值,下面是个例子:

select * from table(
dbms_xplan.display_awr('9yaqj3djhwxa2',nullnull,'outline peeked_binds')
);

关于使用dbms_xplan查找和操作执行计划的内容方面还有很多变化,也随着Oracle的新版本变得更多样化,最近的版本甚至可以输出计划中的不同点,其中一个最有用的小特性与如何填充AWR有关而不是从AWR中获取报告。11g中,你可以将一个SQL_ID标记为"感兴趣",当AWR快照进程在创建快照时会捕获任何关于该语句可用的信息。因为除非该语句是"top N"的语句,否则它不会出现在AWR报告中,但是你可以使用awrsqrpt.sql或者dbms_xplan.display_awr()来获得计划。
如果你想标记某条SQL,你可以调用dbms_workload_repository包:

executedbms_workload_repository.add_colored_sql({sql_id})
--
-- 输出当前被标记的语句
--
select * fromwrm$_colored_sql;
--
-- 解除语句标记
--
executedbms_workload_repository.remove_colored_sql({sql_id})

这个过程的好处是(甚至可以针对一些效率很高的语句),当性能较好的应用突然变慢了,如果你标记了所有进程执行的语句,那么你可以很轻松的找到出现什么问题以及执行计划是什么时候改变的。

Conclusion


尽管我们没有列举出所有生成或者获取执行计划的方法,但是我们学习了足够的原理保证我们可以十分精确地获得我们需要检查的语句执行时的环境,也学习了如何获得一些历史的、不在内存里的执行计划;还有一种保证我们所需要的语句总是会被AWR快照捕捉的方法。
下一篇文章我们会来学习一些基本的解释执行计划的原理,从简单的select语句开始,使用视图来区分连接顺序,访问方式和连接方式。 
原文链接:
https://www.red-gate.com/simple-talk/sql/oracle/execution-plans-part-2-things-to-see/
原文作者:Jonathan Lewis

 

 

| 译者简介

林锦森·沃趣科技数据库技术专家

沃趣科技数据库工程师,多年从事Oracle数据库,较丰富的故障处理、性能调优、数据迁移及备份恢复经验



相关链接

MySQL 一个让你怀疑人生的hang死现象

揭秘 MySQL 主从环境中大事务的传奇事迹

MySQL 执行DDL语句 hang住了怎么办?

手把手教你认识OPTIMIZER_TRACE

MySQL行级别并行复制能并行应用多少个binlog group?

binlog server还是不可靠吗?

MySQL binlog基于时间点恢复数据失败是什么鬼?

开源监控系统Prometheus的前世今生

prometheus监控多个MySQL实例

MySQL问题两则

Kubernetes scheduler学习笔记

执行计划-1:获取执行计划

大数据量删除的思考(四)

大数据量删除的思考(三)

大数据量删除的思考(二)

大数据量删除的思考(一)

统计信息记录表|全方位认识 mysql 系统库

数据库对象信息记录表|全方位认识 mysql 系统库

访问权限控制系统|全方位认识 mysql 系统库

权限系统表 | 全方位认识 mysql 系统库

Oracle RAC Cache Fusion 系列十四:Oracle RAC CR Server Part One

Oracle RAC Cache Fusion 系列十三:PCM资源访问

Oracle RAC Cache Fusion 系列十二:Oracle RAC Enqueues And Lock Part 3

Oracle RAC Cache Fusion 系列十一:Oracle RAC Enqueues And Lock Part 2

Oracle RAC Cache Fusion 系列十:Oracle RAC Enqueues And Lock Part 1


更多干货,欢迎来撩~




推荐阅读
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • Day2列表、字典、集合操作详解
    本文详细介绍了列表、字典、集合的操作方法,包括定义列表、访问列表元素、字符串操作、字典操作、集合操作、文件操作、字符编码与转码等内容。内容详实,适合初学者参考。 ... [详细]
  • WhenIusepythontoapplythepymysqlmoduletoaddafieldtoatableinthemysqldatabase,itdo ... [详细]
author-avatar
纠结不停的孩子
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有