查询优化手段和gather_plan_statistics hint:

在10g以后我们可以通过利用gather_plan_statistics提示来了解更多的SQL执行统计信息,具体使用方法如下:
如果在statistics_level参数设置为ALL,或者执行的sql使用了gather_plan_statistics hint,则在sql执行后,会在v$sql_plan_statistics_all视图中查到SQL的执行统计信息,例如逻辑读,物理读,基数等等。这些数据对于性能诊断有着非常大的帮助。同时v$sql_plan中的执行计划,与通过EXPLAIN PLAN得到的执行计划相比,前者是oracle执行sql时真正使用的执行计划,而后者则可能不是真正的执行计划;同时有的时候,执行过的sql使用了绑定变量,而oracle在解析sql时通常会进行绑定变量窥探,这个时候我们不能使用EXPLAIN PLAN来得到那个sql的执行计划,就算得到的跟那个sql的真实的执行计划是不一样的,所以有时我们更愿意直接从v$sql_plan中得到执行计划。
下面结合tom的文章实例讲一下这个hint得用法:原文:http://www.oracle.com/technetwork/issue-archive/2014/14-nov/o64asktom-2298498.html

---------------------------------------------------------------------------------

一个查询调优的例子:

SQL> create table t

 as

 select case when mod(rownum,200000) = 0 then 5

             else mod(rownum,4)

         end X,

        rpad( 'x', 100, 'x' ) data

   from dual

 connect by level <= 1000000

 /

 

 --此处为了迷惑优化器而制造了分布不均的数据(skew data)

 SQL> create index t_idx on t(x);

Index created.





SQL> exec dbms_stats.gather_table_stats( user, 'T' );

PL/SQL procedure successfully completed.





SQL> select x, count(*)

   from t

  group by x

  order by x

 /





 X   COUNT(*)

———————————  ———————————

         0     249995

         1     250000

         2     250000

         3     250000

         5          5





SQL> select /*+ gather_plan_statistics */

        count(data)

   from t

  where x = 5;

/





--查看上面查询执行计划

SQL>  select *

   from table(

         dbms_xplan.display_cursor( format=> 'allstats last' )

         )

 /

 

 PLAN_TABLE_OUTPUT

——————————————————————————————————

SQL_ID  cdwn5mqb0cpg1, child number 0

——————————————————————————————————

select /*+ gather_plan_statistics */        

count(data)   

from t  

where x = 5





Plan hash value: 2966233522





———————————————————————————————————————————————————————————————————————————

| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   |

———————————————————————————————————————————————————————————————————————————

|   0 | SELECT STATEMENT   |      |      1 |        |      1 |00:00:00.08 |

|   1 |  SORT AGGREGATE    |      |      1 |      1 |      1 |00:00:00.08 |

|*  2 |   TABLE ACCESS FULL| T    |      1 |    200K|      5 |00:00:00.08 |

———————————————————————————————————————————————————————————————————————————





Predicate Information (identified by operation id):

———————————————————————————————————————————————————————————————————————————





   2 - filter("X"=5)





20 rows selected.





--可以看到执行计划走了全表扫描并且E-Rows,即预估基数为200K而A-rows,即实际返回基数为5差距相当大(a huge difference)。原因就是优化器对X列上分布不均的数据没有察觉。

--此时,我们需要提供X列上的直方图(histogram)让优化器掌控全面的基数信息。

SQL> select histogram

    from user_tab_columns

   where table_name = 'T'

     and column_name = 'X';





HISTOGRAM

---------------

NONE





SQL> exec dbms_stats.gather_table_stats( user, 'T',
no_invalidate=>false );





SQL> select histogram

    from user_tab_columns

   where table_name = 'T'

     and column_name = 'X';





HISTOGRAM

---------------

FREQUENCY





----此处是用NO_INVALIDATE参数使之前的依赖游标失效,保证下次运行该查询执行硬解析(hard parse)

--再次执行前面的查询操作,查看运行时计划信息

PLAN_TABLE_OUTPUT

——————————————————————————————————

SQL_ID  cdwn5mqb0cpg1, child number 0

——————————————————————————————————

select /*+ gather_plan_statistics */        

count(data)   

from t  

where x = 5





Plan hash value: 1789076273





————————————————————————————————————————————————————————————————————————

| Id | Operation                    | Name  | Starts | E-Rows | A-Rows |

————————————————————————————————————————————————————————————————————————

|  0 | SELECT STATEMENT             |       |      1 |        |      1 |

|  1 |  SORT AGGREGATE              |       |      1 |      1 |      1 |

|  2 |   TABLE ACCESS BY INDEX ROWID| T     |      1 |    182 |      5 |

|* 3 |    INDEX RANGE SCAN          | T_IDX |      1 |    182 |      5 |

————————————————————————————————————————————————————————————————————————

--------------

|   A-Time   |

--------------

|00:00:00.01 |

|00:00:00.01 |

|00:00:00.01 |

|00:00:00.01 |

Predicate Information (identified by operation id):

————————————————————————————————————————————————————————————————————————





   3 - access("X"=5)





21 rows selected.





--此时执行计划走的是索引范围扫描且E-Rows已经很接近A-Rows,执行时间也大大缩减。

--这里你可能会犯嘀咕:咋第一次收集表信息时没有生成直方图?

看下tom的原话:

This change is likely due to the default value of the METHOD_OPT parameter used with DBMS_STATS. In Oracle Database 10g, the METHOD_OPT parameter defaults to a SIZE AUTO. After you ran a query, the database remembered the predicates and updated a dictionary table, SYS.COL_USAGE$. Then, the next time you ran DBMS_STATS to gather statistics on these tables, DBMS_STATS queried that table to find out what columns should have histograms collected automatically, based on past query workload. It looked at your predicates and said, "Hmm, these columns are candidates for histograms based on the queries the end users have been running."

听起来很神奇吧?事实却是如此!









 

 △补充1:关于管道函数dbms_xplan.display_cursor( format=> 'allstats last' )要解释下几个参数的取值含义:

 ---   function display_cursor(sql_id           varchar2 default null,

  ---                           cursor_child_no  integer default 0,

  ---                           format           varchar2 default 'TYPICAL')

  ---

  ---   - sql_id: 

                  指定SQL_ID取值为V$SQL.SQL_ID, V$SESSION.SQL_ID, 

                  或者V$SESSION.PREV_SQL_ID,如果不指定则默认为最后执行语句SQL_ID

  ---   - cursor_child_no:


指定sql游标的子号,取值为V$SQL.CHILD_NUMBER 或者 in V$SESSION.SQL_CHILD_NUMBER,V$SESSION.PREV_CHILD_NUMBER,


此参数只有指定sql_id情况下才有效。如果不指定,则指定sql_id下所有子游标都显示。

  ---   - format:

  ---        
指定输出列,值取自视图:v$sql_plan_statistics_all.

  ---

  ---        IOSTATS: 


 假设基本计划统计在SQL执行时已收集(使用gather_plan_statistics提示或设置statistics_level参数为ALL)

---               此格式将展示所有游标执行的(或仅最后执行游标)IO统计。

  ---        MEMSTATS: 

---
  假设PGA内存管理开启(例如:pga_aggregate_target参数设置为非0值),此格式允许展示内存管理统计


 (例如:操作执行模式,内存使用,溢出到磁盘字节数)

  ---        ALLSTATS: 指定'IOSTATS MEMSTATS'的快捷命令

  ---

  ---        LAST: 

  ---              此格式就是指定仅显示最后执行sql的统计

  ---

  ---        Also, the following two formats are still supported for backward

  ---        compatibility: 另外以下2个参数为了向后兼容而保留

  ---

  ---        'RUNSTATS_TOT':  Same as 'IOSTATS', i.e. displays IO statistics

  ---                         for all executions of the specified cursor.

  ---        'RUNSTATS_LAST': Same as 'IOSTATS LAST', i.e. displays the runtime

  ---                         statistics for the last execution of the cursor.

  ---   权限要求:

             必须具有:SELECT ON V$SQL_PLAN_STATISTICS_ALL,V$SQL, 和 V$SQL_PLAN权限。

 

 △补充2:还可以使用另一路径查询SQL运行时执行计划:

 HR@orcl> select /*+ gather_plan_statistics emp_plan*/count(1) from employees;





  COUNT(1)

----------

       107

HR@orcl> SELECT SQL_ID,CHILD_NUMBER FROM V$SQL  WHERE SQL_TEXT LIKE '%emp_plan%' and SQL_TEXT NOT LIKE '%V$SQL%';





SQL_ID        CHILD_NUMBER

------------- ------------

2c5q2d8489ybt            0





HR@orcl> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('2c5q2d8489ybt',0,'ALL IOSTATS LAST'));





PLAN_TABLE_OUTPUT

-----------------------------------------------------------------------------------------------------------------------------------





SQL_ID  2c5q2d8489ybt, child number 0

-------------------------------------

select /*+ gather_plan_statistics emp_plan*/count(1) from employees





Plan hash value: 3580537945





----------------------------------------------------------------------------------------------------------------------------

| Id  | Operation        | Name         | Starts | E-Rows | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |

----------------------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT |              |      1 |        |     1 (100)|          |      1 |00:00:00.02 |       1 |      1 |

|   1 |  SORT AGGREGATE  |              |      1 |      1 |            |          |      1 |00:00:00.02 |       1 |      1 |

|   2 |   INDEX FULL SCAN| EMP_EMAIL_UK |      1 |    107 |     1   (0)| 00:00:01 |    107 |00:00:00.02 |       1 |      1 |

----------------------------------------------------------------------------------------------------------------------------





Query Block Name / Object Alias (identified by operation id):

-------------------------------------------------------------





   1 - SEL$1

   2 - SEL$1 / EMPLOYEES@SEL$1





Column Projection Information (identified by operation id):





PLAN_TABLE_OUTPUT

-----------------------------------------------------------------------------------------------------------------------------------





-----------------------------------------------------------





   1 - (#keys=0) COUNT(*)[22]









已选择25行。

---------------------------------------

Dylan    Presents.

ORACLE查询优化及gather_plan_statistics hint的更多相关文章

  1. Oracle 查询优化的基本准则详解

      注:报文来源:想跌破记忆寻找你 < Oracle 查询优化的基本准则详解 > Oracle 查询优化的基本准则详解 1:在进行多表关联时,多用 Where 语句把单个表的结果集最小化, ...

  2. 【书评:Oracle查询优化改写】第三章

    [书评:Oracle查询优化改写]第三章 BLOG文档结构图       导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 隐含参数 ...

  3. oracle 查询优化改写

    -----------书籍: oracle 查询优化改写-----------第1个“C###oracle”为登录数据库的用户名,第2个“oracleChange”为登录数据库的密码“oracleCh ...

  4. 《Oracle查询优化改写技巧与案例》学习笔记-------使用数字篇

    一个系列的读书笔记,读的书是有教无类和落落两位老师编写的<Oracle查询优化改写技巧与案例>. 用这个系列的读书笔记来督促自己学习Oracle,同时,对于其中一些内容,希望大家看到以后, ...

  5. 【书评:Oracle查询优化改写】第14章 结尾章

    [书评:Oracle查询优化改写]第14章 结尾章 一.1  相关参考文章链接 前13章的链接参考相关连接: [书评:Oracle查询优化改写]第一章 http://blog.itpub.net/26 ...

  6. 【书评:Oracle查询优化改写】第五至十三章

    [书评:Oracle查询优化改写]第五至十三章 一.1  BLOG文档结构图 一.2  前言部分 一.2.1  导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知 ...

  7. 【书评:Oracle查询优化改写】第四章

    [书评:Oracle查询优化改写]第四章 BLOG文档结构图 一.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① check的 ...

  8. 【书评:Oracle查询优化改写】第二章

    [书评:Oracle查询优化改写]第二章 BLOG文档结构图 在上一篇中http://blog.itpub.net/26736162/viewspace-1652985/,我们主要分析了一些单表查询的 ...

  9. Oracle中常见的Hint(一)

    Oracle中的Hint可以用来调整SQL的执行计划,提高SQL执行效率.下面分类介绍Oracle数据库中常见的Hint.这里描述的是Oracle11gR2中的常见Hint,Oracle数据库中各个版 ...

  10. Mssql迁移至Oracle 查询优化

    针对Oracle的查询优化 a.避免使用nclob类型字段,可以通过排除此类型的字段,优化查询b.避免对字段进行NULL值判断,如:SELECT * FROM  TABLE WHERE COL IS ...

随机推荐

  1. Linux-关机重启和注销

  2. [转帖]使用 BR 命令行备份恢复

    TiDB试用 来源:TiDB  浏览 404 扫码 分享 2021-04-20 20:49:42 使用 BR 命令行进行备份恢复 BR 命令行描述 命令和子命令 常用选项 使用 BR 命令行备份集群数 ...

  3. [转帖]k8s之PV、PVC、StorageClass详解

    https://zhuanlan.zhihu.com/p/128552232 导读 上一篇写了共享存储的概述以及一个简单的案例演示.这一篇就写一下PV和PVC. PV是对底层网络共享存储的抽象,将共享 ...

  4. Nginx与Tomcat作为前端服务器的性能比较

    Nginx与Tomcat作为前端服务器的性能比较 摘要 最近总遇到使用tomcat还是使用nginx进行前端文件访问的争论 想着出差周末在酒店, 可以自己进行一下简单的测试. 希望能够对未来的工作进行 ...

  5. elementui中el-checkbox 选中时的详细介绍

    checkbox-group 把多个checkbox管理为一组(需要注意的坑) 很多时候我们需要会遇见这样的场景. 比如用户需要选择多个值. 这个时候我们需要把多个 checkbox 放置在check ...

  6. vue插件实现表格拖拽 sortable 遇见的坑

    下载插件 npm install sortable.js --save (下载的时候一定要这样去下载,不要去下载 npm install sortable--save ) 因为sortable.js和 ...

  7. 【K哥爬虫普法】百亿电商数据,直接盗取获利,被判 5 年!

    我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...

  8. 【JS 逆向百例】医保局 SM2+SM4 国产加密算法实战

    关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...

  9. Docker部署Jekyll

    1. 起因 前两天终于下单买了个域名,10年的使用期限.既然有了域名,那自己的博客就可以搞起来了. 现在博客的记录用的是Jekyll+Github Pages,所以决定之后自己的博客网站也采用Jeky ...

  10. 在K8S中,静态、动态、自主式Pod有何区别?

    在Kubernetes(简称K8s)中,静态Pod.自主式Pod和动态Pod是不同管理方式下的Pod类型,它们的区别主要体现在创建和管理方式上: 静态Pod: 静态Pod是由kubelet直接管理的, ...