当前位置: 首页 > news >正文

动态采样大法好,让Oracle执行计划一步到位!

作者介绍

蒋健云趣网络科技联合创始人,11g OCM,多年Oracle设计、管理及实施经验,精通数据库优化,Oracle CBO及并行原理,曾为多个行业的客户的 Oracle 系统实施小型机到 X86跨平台迁移和数据库优化服务。云趣鹰眼监控核心设计和开发者,资深Python Web开发者。(文章审校:杨建荣)

 

动态采样介绍

 

Oracle 动态采样(Dynamic Sampling,12c 称为 Dynamic statistics),是对统计信息的一个重要补充,当数据动态变化,无法用典型的统计信息描述时,动态采样可以给在解析时对表中数据进行采样,为优化器提供准确的估算值(cardinality)。动态采样的主要有以下几个应用场景:

 

  • 一个经典的场景就是业务场景中的临时表,比如 ETL 数据清洗转换过程中的临时表,比如 BI 系统中存放计算报表结果的临时表。这些临时表可能是 Oracle 中的 global temporary table,也可能是正常的堆表。因为临时表中的数据时动态变化的,不同时间点,临时表中的数据量变化很大,没有一种合适的统计信息使优化器产生合适的执行计划。这种场景适合采用动态采样技术,通常会删除临时表上的统计信息,并且锁定统计信息,不让搜集统计信息的 Job 更新临时表上的统计信息,查询临时表时,优化器会对临时表进行动态采样,以确定临时表的 cardinality。

 

  • 另一个场景是在单表上使用组合过滤条件,并且组合过滤条件并不是简单的相等操作,或者在过滤列上使用转换函数,无法使用 column group 扩展统计信息,简单使用多个列上的统计信息也无法产生合适的统计信息。

 

  • 12c 之前,动态采样只能预估单表 cardinality,12c 版本,Oracle 对动态采样做了很大的增强,可以估算 group by 的聚合结果集和连接结果集的 cardinality。

 

使用动态采样,优化器往往可以获得高质量的估算值,从而产生更优化的执行计划。本文将介绍三种动态采样的适用场景。

 

临时表和动态采样

 

优化器动态采样解析

 

实际案例

 

金融行业客户 CRM 系统的分析语句执行时间经常需要5分钟以上,通过分析 Top SQL的执行计划,发现执行计划的估算值偏差离谱,比如下图SQL Monitor 报告中,对于表P_CUST_STAT,优化器估算值为1,实际值为一千四百万行。导致后续连接方式为 nested loop,被驱动表被访问了一千四百万次。

 

20170322101314216.jpg

 

通过表的统计信息,可以发现10月9号搜集统计信息时,表P_CUST_STAT中没有数据,Num_Rows为0行, 所以优化器估算为1行。虽然P_CUST_STAT是正常对表,但是在应用中被用于临时表,数据是动态生成和删除的。

 

20170322101323631.jpg

 

另一个例子,下图 SQL Monitor 报告中,表B_S_CUST_STAT的过滤条件为Data_date = to_date(20161008,'yyyymmdd'), 估算值同样为一行,实际值为一千四百万行,导致后续连接方式为 nested loop outer,被驱动视图表访问了一千四百万次。

 

20170322101332266.jpg

 

通过表B_S_CUST_STAT的统计信息,统计信息收集时间为10月9号早上8点,Num_Rows为一千三百七十万行记录,看起来表上的统计信息是正确的。

 

20170322101340999.jpg

 

继续查看B_S_CUST_STAT列上的统计信息,Data_date 列上只有一个唯一值,为10月7号。表B_S_CUST_STAT只存放一天的数据,当统计信息搜集时,表中的数据为10月7号的数据。之后,数据被替换为10月8号的数据,统计信息并没有及时更新,导致当天之后对表 P_CUST_STAT的使用 Data_date = to_date(20161008,'yyyymmdd') 的查询的估算值都为1。

 

20170322101347776.jpg

 

create or replace function raw_to_date(i_raw raw)

return date

as

m_n date;

begin

dbms_stats.convert_raw_value(i_raw,m_n);

return m_n;

end;

/

select raw_to_date('78740A07010101') stats_value from dual;

STATS_VALUE

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

2016-10-07 00:00:00

 

解决方案

 

删除表B_S_CUST_STAT和P_CUST_STAT的统计信息并且进行锁定,保证后续对临时表的查询会使用动态采样,得到准确的估算值。

 

Exec dbms_stats.delete_table_stats(‘CRM’,’B_S_CUST’);

Exec dbms_stats.lock_table_stats(‘CRM’,’B_S_CUST’);

Exec dbms_stats.delete_table_stats(‘CRM’,’P_CUST_STAT’);

Exec dbms_stats.lock_table_stats(‘CRM’,’P_CUST_STAT’);

 

复杂查询的动态采样

 

对于有复杂的过滤条件的sql, 为了在执行计划中得到正确的cardinality, 统计信息未必有帮助, 包括extended statistics. 比如下面in和like的组合条件, 或者where条件中使用了自定义的函数。

 

status in (‘COM’, ‘ERR’) and v1 like ‘10%’

 

这时候dynamic sampling可能是唯一的选择。下面是一个例子, 采用level为6的采样之后,cardinality更为接近真实的数据。

 

构造一个1百万行数据的测试表,搜集统计信息。

 

20170322101355829.jpg

 

测试 SQL,估算值为395行,实际值为11113行,差距为30倍左右。

 

20170322101402768.jpg

 

使用动态采样,级别为6,估算值为16595行,实际为11113行,差距不到2倍,估算值的质量大幅提升。

 

20170322101413909.jpg

 

12c 动态采样的增强,对连接和 group by 结果集的统计

 

测试SQL结果集为13行,12c中采样级别设为11,实际为auto时,CBO估算为12行,准确性很高,并且在表上有统计信息的情况下依然可以进行采样(采样级别设为6时,不使用采样,清除表上的统计信息后,可发现采样级别为6的时候,CBO估算值15743行,差别很大)

 

20170322101421898.jpg

20170322101429806.jpg

20170322101438904.jpg

20170322101446101.jpg

 

总结

 

Oracle 动态采样在性能优化上有诸多应用场景,12c中更是得到加强,更深入了解动态采样的特性对性能优化有着重要的意义。

原文发布时间为:2017-03-22

本文来自云栖社区合作伙伴DBAplus


相关文章:

  • 图文并茂超详细搭建redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
  • .Net接口调试与案例
  • git pull 和本地文件冲突解决
  • SQL Server 中BIT类型字段增删查改那点事
  • python写的百度图片爬虫
  • 《Netty官方文档》本地传输接口
  • tomcat java.lang.OutOfMemoryError: PermGen space解决
  • OTL调用存储过程/函数及注意事项
  • Yahoo的流计算引擎基准测试
  • Js基本方法
  • 【Java集合源代码剖析】TreeMap源代码剖析
  • Transient修饰符的使用
  • 【算法】 算法和数据结构绪论
  • 【转】Servlet 生命周期、工作原理
  • Openssl源代码整理学习---含P7/P10/P12说明
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • Mysql5.6主从复制
  • node.js
  • PAT A1017 优先队列
  • windows下使用nginx调试简介
  • 机器学习 vs. 深度学习
  • 开源SQL-on-Hadoop系统一览
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 全栈开发——Linux
  • 使用agvtool更改app version/build
  • 走向全栈之MongoDB的使用
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (C++)八皇后问题
  • (Python第六天)文件处理
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (五)Python 垃圾回收机制
  • .aanva
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET Micro Framework初体验
  • .Net Redis的秒杀Dome和异步执行
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .sh 的运行
  • @Autowired 与@Resource的区别
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...
  • @ModelAttribute使用详解
  • [14]内置对象
  • [20170705]diff比较执行结果的内容.txt
  • [bzoj1912]异象石(set)
  • [C# 开发技巧]实现属于自己的截图工具
  • [C#]winform部署yolov9的onnx模型
  • [DNS网络] 网页无法打开、显示不全、加载卡顿缓慢 | 解决方案
  • [Docker]十一.Docker Swarm集群raft算法,Docker Swarm Web管理工具