为什么需要SQL Profile

Why oracle need SQL Profiles,how it work and what are SQL Profiles...

使用DBMS_XPLAN.DISPLAY分析SQL执行计划,通常会看到Note中有类似下面这样的提示;

  1. Note
  2. -----
  3.  
  4. - SQL profile "SYS_SQLPROF_0158283a9b920000" used for this statement

SQL profile由人为手工创建或在Automatic SQL Tunning阶段由SQL tuning advisor创建,它看起来有如下的意思:

  1. 在优化器评估SQL时使用了额外的对象帮助完成评估;
  2. 对象改变了优化器原先的评估计划;

当看到这些信息,比较关心的是这个对象(SLQ profile)是什么?它做了什么?是否真的需要它?带着这些疑问学习和探索,最终决解了遇到的问题。

  1. SQL> @i
  2. USERNAME INST_NAME HOST_NAME SID SERIAL# VERSION STARTED SPID OPID CPID SADDR PADDR
  3. -------------------- -------------------- ------------------------- ----- -------- ---------- -------- ---------- ----- --------------- ---------------- ----------------
  4. OPS$SYWU sydb sywu.com 288 22197 11.2.0.4.0 20160421 13736 46 3392:1312 0000000071FE0DA0 0000000072149F40

遇到的问题

假设有这样一张类似订单的表orders;

  1. create table orders(order_no,order_date)
  2. as
  3. select
  4. level,cast(sysdate-level/24 as date)
  5. from
  6. dual
  7. connect by level<=5E5;
  8. SQL> @desc orders
  9. Name Null? Type
  10. ------------------------------- -------- ----------------------------
  11. 1 ORDER_NO NUMBER
  12. 2 ORDER_DATE DATE

保存订单信息,order_date上创建了索引。

  1. create index idx_orders_dt on orders(order_date);

在交易中可能经常遇到某些原因导致交易延期的情况,为了测试这个问题,开发人员添加了未来某一天这样的日期值测试;这里用一个清晰的时间来代替未来的日期;

  1. INSERT INTO ORDERS VALUES (-1, DATE '9999-01-01');

和正常使用的一样,该表定期收集了统计信息;

  1. exec dbms_stats.gather_table_stats(user,'orders', cascade => true);

当系统查询当天的交易记录时发现优化器使用全表扫描,并非索引扫描;

  1. -------------------------------------------------------------------------------------------------------------------------------
  2. | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | Reads |
  3. -------------------------------------------------------------------------------------------------------------------------------
  4. | 0 | SELECT STATEMENT | | 1 | | | 130 (100)| | 10 |00:00:00.23 | 329 | 323 |
  5. |* 1 | TABLE ACCESS FULL| ORDERS | 1 | 496K| 6302K| 130 (26)| 00:00:02 | 10 |00:00:00.23 | 329 | 323 |
  6. -------------------------------------------------------------------------------------------------------------------------------
  7. Query Block Name / Object Alias (identified by operation id):
  8. -------------------------------------------------------------
  9. 1 - SEL$1 / ORDERS@SEL$1
  10. Outline Data
  11. -------------
  12. /*+
  13. BEGIN_OUTLINE_DATA
  14. IGNORE_OPTIM_EMBEDDED_HINTS
  15. OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
  16. DB_VERSION('11.2.0.4')
  17. ALL_ROWS
  18. OUTLINE_LEAF(@"SEL$1")
  19. FULL(@"SEL$1" "ORDERS"@"SEL$1")
  20. END_OUTLINE_DATA
  21. */
  22. Predicate Information (identified by operation id):
  23. ---------------------------------------------------
  24. 1 - filter("ORDER_DATE">=TRUNC(SYSDATE@!,'fmdd'))
  25. Column Projection Information (identified by operation id):
  26. -----------------------------------------------------------
  27. 1 - "ORDERS"."ORDER_NO"[NUMBER,22], "ORDER_DATE"[DATE,7]

显然对于这样一张交易记录表,实际当天的记录数据只占全表数据量的4.1%左右,使用索引扫描的方式开销小于全表扫描,但优化器对范围评估错误。接着使用DBMS_SQLTUNE分析SQL;

  1. var task_name varchar2(30)
  2. BEGIN
  3. :task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
  4. sql_text => 'select * from orders where order_date>=trunc(sysdate,''DD'')',
  5. user_name => user,
  6. scope => 'COMPREHENSIVE',
  7. time_limit => 60,
  8. task_name => 'orders_tuning_task');
  9. END;
  10. /

执行分析;

  1. alter session set events '10046 trace name context forever,level 12';
  2. exec DBMS_SQLTUNE.execute_tuning_task(task_name => :task_name);

分析结果;

  1. col REPORT_TUNING format a200
  2. select
  3. dbms_sqltune.report_tuning_task(:task_name) REPORT_TUNING
  4. from
  5. dual;
  6. REPORT_TUNING
  7. ----------------------------------------------------------------------------------------------------------------------
  8. GENERAL INFORMATION SECTION
  9. -------------------------------------------------------------------------------
  10. Tuning Task Name : orders_tuning_task
  11. Tuning Task Owner : OPS$SYWU
  12. Workload Type : Single SQL Statement
  13. Scope : COMPREHENSIVE
  14. Time Limit(seconds): 60
  15. Completion Status : COMPLETED
  16. Started at : 11/07/2016 21:43:25
  17. Completed at : 11/07/2016 21:43:27
  18. -------------------------------------------------------------------------------
  19. Schema Name: OPS$SYWU
  20. SQL ID : 9ybj4xdc5hsrb
  21. SQL Text : select * from orders where order_date>=trunc(sysdate,'DD')
  22. -------------------------------------------------------------------------------
  23. FINDINGS SECTION (1 finding)
  24. -------------------------------------------------------------------------------
  25. 1- SQL Profile Finding (see explain plans section below)
  26. --------------------------------------------------------
  27. A potentially better execution plan was found for this statement.
  28. Recommendation (estimated benefit: 98.78%)
  29. ------------------------------------------
  30. - Consider accepting the recommended SQL profile.
  31. execute dbms_sqltune.accept_sql_profile(task_name =>
  32. 'orders_tuning_task', task_owner => 'OPS$SYWU', replace => TRUE);
  33. Validation results
  34. ------------------
  35. The SQL profile was tested by executing both its plan and the original plan
  36. and measuring their respective execution statistics. A plan may have been
  37. only partially executed if the other could be run to completion in less time.
  38. Original Plan With SQL Profile % Improved
  39. ------------- ---------------- ----------
  40. Completion Status: COMPLETE COMPLETE
  41. Elapsed Time (s): .041546 .000132 99.68 %
  42. CPU Time (s): .029895 .0001 99.66 %
  43. User I/O Time (s): .015204 .000032 99.78 %
  44. Buffer Gets: 328 4 98.78 %
  45. Physical Read Requests: 45 0 100 %
  46. Physical Write Requests: 0 0
  47. Physical Read Bytes: 10682368 9830 99.9 %
  48. Physical Write Bytes: 0 0
  49. Rows Processed: 10 10
  50. Fetches: 10 10
  51. Executions: 1 1
  52. Notes
  53. -----
  54. 1. Statistics for the original plan were averaged over 10 executions.
  55. 2. Statistics for the SQL profile plan were averaged over 10 executions.
  56. -------------------------------------------------------------------------------
  57. EXPLAIN PLANS SECTION
  58. -------------------------------------------------------------------------------
  59. 1- Original With Adjusted Cost
  60. ------------------------------
  61. Plan hash value: 1275100350
  62. ----------------------------------------------------------------------------
  63. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  64. ----------------------------------------------------------------------------
  65. | 0 | SELECT STATEMENT | | 18 | 234 | 130 (26)| 00:00:02 |
  66. |* 1 | TABLE ACCESS FULL| ORDERS | 18 | 234 | 130 (26)| 00:00:02 |
  67. ----------------------------------------------------------------------------
  68. Predicate Information (identified by operation id):
  69. ---------------------------------------------------
  70. 1 - filter("ORDER_DATE">=TRUNC(SYSDATE@!,'fmdd'))
  71. 2- Using SQL Profile
  72. --------------------
  73. Plan hash value: 3364688013
  74. ---------------------------------------------------------------------------------------------
  75. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  76. ---------------------------------------------------------------------------------------------
  77. | 0 | SELECT STATEMENT | | 18 | 234 | 3 (0)| 00:00:01 |
  78. | 1 | TABLE ACCESS BY INDEX ROWID| ORDERS | 18 | 234 | 3 (0)| 00:00:01 |
  79. |* 2 | INDEX RANGE SCAN | IDX_ORDERS_DT | 10 | | 2 (0)| 00:00:01 |
  80. ---------------------------------------------------------------------------------------------
  81. Predicate Information (identified by operation id):
  82. ---------------------------------------------------
  83. 2 - access("ORDER_DATE">=TRUNC(SYSDATE@!,'fmdd'))
  84. -------------------------------------------------------------------------------

oracle通过分析发现了问题,产生了新的执行计划,并对比两个执行计划,新的执行计划改善90%+的性能,并且改善性能问题只需要同意使用SQL Profile即可;然后允许数据库使用SQL Profile。

  1. exec dbms_sqltune.ACCEPT_SQL_PROFILE(TASK_NAME=>:task_name);

再次执行SQL时,优化器使用了SQL Profile和新的执行计划。

  1. select * from orders where order_date>=trunc(sysdate,'DD');
  2.  
  3. SQL_ID 3zcvw1pxfcypm, child number 0
  4. -------------------------------------
  5. select * from orders where order_date>=trunc(sysdate,'DD')
  6.  
  7. Plan hash value: 3364688013
  8.  
  9. ---------------------------------------------------------------------------------------------------------------------------------------
  10. | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
  11. ---------------------------------------------------------------------------------------------------------------------------------------
  12. | 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 10 |00:00:00.01 | 6 |
  13. | 1 | TABLE ACCESS BY INDEX ROWID| ORDERS | 1 | 18 | 234 | 3 (0)| 00:00:01 | 10 |00:00:00.01 | 6 |
  14. |* 2 | INDEX RANGE SCAN | IDX_ORDERS_DT | 1 | 10 | | 2 (0)| 00:00:01 | 10 |00:00:00.01 | 3 |
  15. ---------------------------------------------------------------------------------------------------------------------------------------
  16.  
  17. Query Block Name / Object Alias (identified by operation id):
  18. -------------------------------------------------------------
  19.  
  20. 1 - SEL$1 / ORDERS@SEL$1
  21. 2 - SEL$1 / ORDERS@SEL$1
  22.  
  23. Outline Data
  24. -------------
  25.  
  26. /*+
  27. BEGIN_OUTLINE_DATA
  28. IGNORE_OPTIM_EMBEDDED_HINTS
  29. OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
  30. DB_VERSION('11.2.0.4')
  31. ALL_ROWS
  32. OUTLINE_LEAF(@"SEL$1")
  33. INDEX_RS_ASC(@"SEL$1" "ORDERS"@"SEL$1" ("ORDERS"."ORDER_DATE"))
  34. END_OUTLINE_DATA
  35. */
  36.  
  37. Predicate Information (identified by operation id):
  38. ---------------------------------------------------
  39.  
  40. 2 - access("ORDER_DATE">=TRUNC(SYSDATE@!,'fmdd'))
  41.  
  42. Column Projection Information (identified by operation id):
  43. -----------------------------------------------------------
  44.  
  45. 1 - "ORDERS"."ORDER_NO"[NUMBER,22], "ORDER_DATE"[DATE,7]
  46. 2 - "ORDERS".ROWID[ROWID,10], "ORDER_DATE"[DATE,7]
  47.  
  48. Note
  49. -----
  50.  
  51. - SQL profile SYS_SQLPROF_01582d15092f0001 used for this statement
  52.  
  53. SQL> @sql 2061925043
  54. Show SQL text, child cursors and execution stats for SQL hash value 2061925043 child OPS$SYWU@sydb_111 report
  55.  
  56. HASH_VALUE CH# PLAN_HASH SQL_TEXT SQL_PROFILE
  57. ---------- ----- ---------- -------------------------------------------------------------------------------------------------------------- ------------------------------
  58. 2061925043 0 3364688013 select * from orders where order_date>=trunc(sysdate,'DD') SYS_SQLPROF_01582d15092f0001
  59.  
  60. CH# PARENT_HANDLE OBJECT_HANDLE PARSES H_PARSES EXECUTIONS FETCHES ROWS_PROCESSED LIOS PIOS SORTS CPU_MS ELA_MS USERS_EXECUTING
  61. ----- ---------------- ---------------- ---------- ---------- ---------- ---------- -------------- ---------- ---------- ---------- ---------- ---------- ---------------
  62. 0 0000000064618858 0000000063A03108 1 3 1 2 10 16 6 0 7.999 8.621 0

Oracle 分析背后做了什么

很惊奇,为什么分析后优化器就能找出问题所在,此时焦点都集中在trace文件了;分析trace文件,发现如下信息;

  1. SELECT /* DS_SVC */ /*+ dynamic_sampling(0) no_sql_tune no_monitoring
  2. optimizer_features_enable(default) opt_param('parallel_execution_enabled',
  3. 'false') result_cache */ COUNT(C1)
  4. FROM
  5. (SELECT /*+ qb_name("innerQuery") NO_INDEX_FFS( "ORDERS") */ 1 AS C1 FROM
  6. "ORDERS" SAMPLE BLOCK(56.8182, 2) SEED(1) "ORDERS") innerQuery
  7. SELECT /* DS_SVC */ /*+ dynamic_sampling(0) no_sql_tune no_monitoring
  8. optimizer_features_enable(default) opt_param('parallel_execution_enabled',
  9. 'false') result_cache */ COUNT(C1)
  10. FROM
  11. (SELECT /*+ qb_name("innerQuery") INDEX_FFS( "ORDERS" "IDX_ORDERS_DT") */ 1
  12. AS C1 FROM "ORDERS" SAMPLE BLOCK(59.5238, 2) SEED(1) "ORDERS" WHERE (
  13. "ORDERS".ORDER_DATE IS NOT NULL)) innerQuery
  14. SELECT /* DS_SVC */ /*+ dynamic_sampling(0) no_sql_tune no_monitoring
  15. optimizer_features_enable(default) opt_param('parallel_execution_enabled',
  16. 'false') result_cache */ COUNT(C1)
  17. FROM
  18. (SELECT /*+ qb_name("innerQuery") NO_INDEX_FFS( "ORDERS") */ 1 AS C1 FROM
  19. "ORDERS" SAMPLE BLOCK(56.8182, 2) SEED(1) "ORDERS" WHERE
  20. ("ORDERS"."ORDER_DATE">=TRUNC(SYSDATE@!,'fmdd'))) innerQuery
  21. SELECT /* DS_SVC */ /*+ dynamic_sampling(0) no_sql_tune no_monitoring
  22. optimizer_features_enable(default) opt_param('parallel_execution_enabled',
  23. 'false') result_cache OPT_ESTIMATE(@"innerQuery", TABLE, "ORDERS",
  24. SCALE_ROWS=3.545138895e-05) */ C1, C2, C3
  25. FROM
  26. (SELECT /*+ qb_name("innerQuery") INDEX( "ORDERS" "IDX_ORDERS_DT") */
  27. COUNT(*) AS C1, 4294967295 AS C2, COUNT(*) AS C3 FROM "ORDERS" "ORDERS"
  28. WHERE ("ORDERS"."ORDER_DATE">=TRUNC(SYSDATE@!,'fmdd'))) innerQuery
  29. /* SQL Analyze(156,0) */ select * from orders where order_date>=trunc(sysdate,'DD')

从trace文件分析得出,oracle做了如下的操作:

  1. 动态采样分析全表数据(无索引);
  2. 动态采样分析表中非空数据(无索引);
  3. 用全表扫描的方式动态采样分析相关的数据;
  4. 用索引扫描的方式动态采样分析相关的数据;
  5. 对比旧的和新的执行计划;

Oracle对比旧的和新的执行计划后,将消耗小的执行计划信息保存到SQL profile中。

优化器的问题

通常优化器相信:

  1. 数据值分布均匀(比如假设:表列数据中,数值2比数值5一样使用频繁);
  2. 数据行分布均匀(比如假设:没有物理cluster或者数据排序);
  3. 对于范围数据是连续的,没有漏缺。

优化器信任收集的统计信息,这些信息包括表行记录数,distinct value,max/min value,直方图信息;换一种通俗的说法,统计信息捕获了表整体形状数据,但有些低级别的信息丢失了。这种分析对于大多数数据来说往往工作得很好,但实际情况中,不可避免的有违反规则的例外,比如对于一张大表,98%的数据可能以随机的方式分配在整个段中(segment),剩余的2%的数据可能只集中在几个数据块中;不幸的是收集统计信息时没有记录这些细节;这就引发一个问题,已经有的统计信息不能完全有效的帮助优化器生成正确的执行计划,所以到了这里问题转变为什么可以弥补或纠正这些信息,让优化器面对这种特定的SQL时可以评估正确,生成好的执行计划。

什么是SQL Profile

通过上面的实验大体将SQL Profile定义为:

  1. 为特定SQL创建和保存执行计划信息;
  2. 使用实际运行时的数据来帮助优化器为特定的SQL评估和生成更好的执行计划;

首先通过dbms_sqltune.create_tunning_task创建任务告诉数据库存在问题的可以改善的SQL,这个操作在11G或以后的版本中可以通过Automatic SQL Tuning在对"most active" SQL 分析时创建;然后运行dbms_sqltune.execute_tuning_task评估,这个过程包括三个主要步骤:

  1. 动态采样分析表数据,获取到真实的实数信息(最重要的比如,Cardinality)
  2. 提供这些真实的实数信息给优化器,让优化器重新评估;
  3. 如果优化器评估出新的执行计划,重复多次运行旧的执行计划和新的执行计划,最后对比性能;

如果优化器试运行得出的结果为:

  1. 优化器评估后产生了新的执行计划;
  2. 新的执行计划比旧的执行计划性能消耗更小,大幅提升性能;

则表明优化器证明旧的评估对于特定的SQL是错误的,一些低级的数据被分析出,进一步,oracle会将这些信息保存供以后使用。但是如何保存这些信息呢?不可能通过定期性的更新统计信息,因为统计信息不包括这些信息。所以,数据库使用一个独立的对象(SQL Profile)保存SQL和这些(cardinality)信息。oracle 以opt_estimate hints的格式保存cardinality信息;
/+ opt_estimate(table, orders, scale_rows=10) */
或者
/
+ opt_estimate(index_scan, orders, IDX_ORDERS_DT, scale_rows=0.001) */
所以如果使用了SQL Profile,评估时默认的cardinality将乘以这些数字,优化器会更真实的查看到表中的数据信息,然后做出评估。

为什么需要SQL Profile的更多相关文章

  1. Oracle 通过sql profile为sql语句加hint

    sql profile最大的优点是在不修改sql语句和会话执行环境的情况下去优化sql的执行效率,适合无法在应用程序中修改sql时.sql profile最常用方法大概是:--创建产生sql tuni ...

  2. SQL profile纵览(10g)

    第一篇:介绍         10g开始,查询优化器(Query optimizer)扩展成自动调整优化器(Automatic Tuning Optimizer).也就是扩展了功能.此时,我们就可以让 ...

  3. SQL Profile 总结(一)

    一.前提概述 在介绍SQL Profile之前,不得不说的一个工具就是SQL Tuning Advisor:这个工具是从Oracle 10g開始引入,它的任务就是分析一个指定的SQL语句,并建议怎样使 ...

  4. SQL Profile (总结4)--使用演示示例

    前提:sql profile工具的相关视图 dba_sql_profile 10g: sys.sqlprof$attr  &  sqlprof$ 11g: sys.sqlobj$data  & ...

  5. 使用COE脚本绑定SQL Profile

    日常运维中,经常会遇到需要绑定好的执行计划的场景. 简单来说,就是将一个sql_id绑定好的plan_hash_value.如果没有使用到绑定变量,还需要把force_match设置为true. 用到 ...

  6. 转://SQL PROFILE

    我们经常会碰到一些线上的SQL问题,因为执行计划不对,可能需要添加HINT才能解决.但是添加HINT就意味着需要修改应用代码.一般一个应用代码的修改.测试及发布,可能需要两三个工作日才可完成.咱们数据 ...

  7. .Oracle固定执行计划之SQL PROFILE概要文件

    1.  引子Oracle系统为了合理分配和使用系统的资源提出了概要文件的概念.所谓概要文件,就是一份描述如何使用系统的资源(主要是CPU资源)的配置文件.将概要文件赋予某个数据库用户,在用户连接并访问 ...

  8. 转 sql profile 绑定 litera and move profile to another db l for spa

    SQL TYPE 1:for bind value sql , first create a good plan with literal and with good  profile. then u ...

  9. 使用SQL Profile及SQL Tuning Advisor固定运行计划

    SQL Profile就是为某一SQL语句提供除了系统统计信息.对象(表和索引等)统计信息之外的其它信息,比方执行环境.额外的更准确的统计信息,以帮助优化器为SQL语句选择更适合的执行计划. SQL ...

随机推荐

  1. 让JS写的更接近OOP

    下面这段代码就是利用JS原型对象,来实现的类的继承DEMO $ 为jquery对象 ////公共方法 // $.oop.newClass=function newClass(obj) { // fun ...

  2. Hyperion Business Modeling for Microsoft Windows (32-bit)

    介质包搜索 常见问题    说明   复查 许可证列表 以确定需要下载的产品程序包. 请选择产品程序包和平台,然后单击“查找”. 如果只有一项结果,则可以看到下载页.如果有多个结果,请选择一个,然后单 ...

  3. asp.net.mvc4在vs2010怎样创建mvc项目及它的结构

    1.打开vs2012,创建mvc项目 文件-->新建--> 项目--> web--> asp.net.Mvc 4web应用程序-->基本模板

  4. C#开发规范总结(个人建议)

    .NET开发编程规范 章程序的版式 版式虽然不会影响程序的功能,但会影响可读性.程序的版式追求清晰.美观,是程序风格的重要构成因素. 可以把程序的版式比喻为"书法".好的" ...

  5. SignalR+Asp.net高频率实时消息传递应用

    1.概述: 使用 ASP.NET 和SignalR 2高频率的实时消息功能.高频率消息在这种情况下就意味着更新发送以固定的速率; 本教程中创建的应用程序显示一个用户可以拖动的形状.在所有其他连接浏览器 ...

  6. Chrome浏览器的Timing分析

    以W3C网站为例: Stalled是浏览器得到要发出这个请求的指令,到请求可以发出的等待时间,一般是代理协商.以及等待可复用的TCP连接释放的时间,不包括DNS查询.建立TCP连接等时间等. SSL( ...

  7. 一个小笔记(8):EN_2

    Why is programming fun? What delights may its practitioner expect as his reward? First is the sheer ...

  8. 常见的几种RuntimeException

    一般面试中java Exception(runtimeException )是必会被问到的问题 常见的异常列出四五种,是基本要求.更多的....需要注意积累了   常见的几种如下:   NullPoi ...

  9. .NET Framework 4.0之Tuple(元组)

    Tuple,是函数式编程的概念之一,早见于Elang.F#等动态语言.Tuple类型像一个口袋,在出门前可以把所需的任何东西一股脑地放在里面.您可以将钥匙.驾驶证.便笺簿和钢笔放在口袋里,您的口袋是存 ...

  10. UltraEdit打开UTF-8文件后显示中文乱码的问题

    左图是UE,默认的编码格式GBK.右图可以看出可修改成UTF-8编码.按钮位置是UE底部状态栏,图3显示怎么开关状态栏. >>>>>>>>>> ...