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

mysql cbo优化器_Oracle约束Constraint对于CBO优化器的作用

进入CBO优化器时代之后,成本计算值决定执行计划的选取已经成为主流。一条性能良好的执行计划建立在尽可能“贴切”的统计量基础上。CBO内部又经历了两个时代——IO Cost和CPU Cost,两者的区别就在于系统统计量(System Statistical)的应用。

RBO时代,执行计划其实也是有评估的。RBO的执行计划评定级别不会像CBO成本粒度那么细,而是15个路径等级评定。等级编号低的执行计划比等级编号高的执行计划更会被选择到。

在这个过程中,我们其实还是忽略了影响执行计划的因素,就是约束(Constraint)。Constraint对于数据库对象很重要,所谓约束,就是建立在数据表、数据列上的规则限制。Constraint的存在目的就是将业务规则融入到数据表设计中。

Constraint确定描述了数据表的一些固有特性,比如非空、外键,就从一个程度上给出了数据表特性的描述。经常性的将Constraint作为一种数据完整性约束的实现,但是对于CBO而言,约束也是搜寻“捷径”执行计划的重要信息来源。从经验上看,约束能够给CBO带来的高效执行计划作用,是不可忽视的。

本篇介绍几个常见的业务场景,说明在合理规划约束的情况下,CBO能够生成更好地执行计划。

--------------------------------------分割线 --------------------------------------

相关阅读:

--------------------------------------分割线 --------------------------------------

1、执行环境介绍

我们同时要使用CBO和RBO进行测试过程,选择Oracle 11g进行测试。

SQL> select * from v$version;

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production

PL/SQL Release 11.2.0.3.0 - Production

CORE 11.2.0.3.0 Production

TNS for Linux: Version 11.2.0.3.0 - Production

NLSRTL Version 11.2.0.3.0 – Production

当前默认使用CBO优化器组件。

SQL> show parameter optimizer

NAME                                TYPE        VALUE

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

optimizer_mode                      string      ALL_ROWS

optimizer_use_sql_plan_baselines    boolean    TRUE

(篇幅原因,有省略……)

2、“null还是not null”大不一样

我们在实际设计数据库中,经常会忽略字段非空设置。不少朋友和开发团队对于这个细节不以为然,认为这个设置就是会影响到插入过程。一些朋友认为:在应用层面验证一下就可以了。但是实际上,null与not null,大不一样!有很多方面的差异和问题,纯应用层面验证是不能解决问题的。

笔者从性能优化器角度,介绍一下忽视not null效果的问题。我们首先创建实验数据表T。

--数据表T

SQL> create table t as select * from dba_objects;

Table created

--其他用途索引

SQL> create index idx_t_id on t(object_id);

Index created

--统计量收集

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

PL/SQL procedure successfully completed

还是我们经常设置的场景,就是没有where条件的count动作。

SQL> explain plan for select count(*) from t;

Explained

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT

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

Plan hash value: 2966233522

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

| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time    |

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

|  0 | SELECT STATEMENT  |      |    1 |  294  (1)| 00:00:04 |

|  1 |  SORT AGGREGATE    |      |    1 |            |          |

|  2 |  TABLE ACCESS FULL| T    | 75609 |  294  (1)| 00:00:04 |

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

9 rows selected

很正常的执行计划,因为需要检索所有的数据行记录,检索数据表所有的记录是比较直观的想法。这个FTS执行计划成本值294。我们修改一下索引列object_id的属性,将其从原先的null设置为not null。

SQL> alter table t modify object_id not null;

Table altered

SQL> explain plan for select count(*) from t;

Explained

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT

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

Plan hash value: 3570898368

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

| Id  | Operation            | Name    | Rows  | Cost (%CPU)| Time    |

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

|  0 | SELECT STATEMENT      |          |    1 |    48  (3)| 00:00:01 |

|  1 |  SORT AGGREGATE      |          |    1 |            |          |

|  2 |  INDEX FAST FULL SCAN| IDX_T_ID | 75609 |    48  (3)| 00:00:01 |

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

9 rows selected

SQL语句中没有where条件,选取的count(*)也没有直接object_id关系。但是执行计划中出现了索引对象,最重要的是执行计划从原来的294下降到48。

观察这个执行计划,路径中出现了Index Fast Full Scan动作,而且没有回表动作。Oracle选择这样的路径思路是这样的:object_id是索引列,所有object_id的取值均在叶子节点上。关键难点在于空置null,Oracle中null值不会进入单键值索引对象叶子节点。这也就是为什么Oracle在object_id不设置为not null时不走索引路径的原因。

Oracle在取巧!在CBO时代,对索引路径的选择是一个非常出巧的地方。RBO时代,十五种等级规则,实际就意味着十五种路径方式。我们看RBO时代,有没有这样的策略。

SQL> explain plan for select /*+rule*/count(*) from t;

Explained

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT

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

Plan hash value: 2966233522

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

| Id  | Operation          | Name |

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

|  0 | SELECT STATEMENT  |      |

|  1 |  SORT AGGREGATE    |      |

|  2 |  TABLE ACCESS FULL| T    |

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

Note

-----

- rule based optimizer used (consider using cbo)

13 rows selected

从上面情况看,RBO时代没有这样的“取巧”过程。

约束not null和null带给我们的不仅仅是数据约束的保证,从这个例子上,可以看到not null还可以带来一些高效的执行计划,实现性能上的提升。

3、主键列的Group By

单纯使用Group By是没有意义的,一般都是伴随着如count、sum等聚合函数方法。另外一个关于Group By的特性是:空值null也会被进行Group By。

主键Primary Key的特性是唯一和非空,如果对其进行Group By,每个对象的操作数量就是1。这个过程其实也是不需要进行真正操作的。

下面我们进行测试。

SQL> explain plan for select empno, count(*) from scott.emp group by empno;

Explained

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT

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

Plan hash value: 1749432681

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

| Id  | Operation            | Name  | Rows  | Bytes | Cost (%CPU)| Time    |

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

|  0 | SELECT STATEMENT    |        |    14 |    56 |    1  (0)| 00:00:01 |

|  1 |  SORT GROUP BY NOSORT|        |    14 |    56 |    1  (0)| 00:00:01 |

|  2 |  INDEX FULL SCAN    | PK_EMP |    14 |    56 |    1  (0)| 00:00:01 |

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

0b1331709591d260c1c78e86d0c51c18.png

相关文章:

  • php结合MySQL的柱状图_jpgraph+php+mysql生成柱状图(含代码)
  • 查看有哪些namespace_Linux操作系统中的namespace是个什么鬼
  • zabbix php mysql_Centos7+PHP5.6+MySQL5.7+Zabbix4.0部署
  • 判别式模型python_判别式模型与生成式模型
  • 双鉴探测器是哪两种探测方式结合_报警的基本知识
  • 虚拟机annaconda连接mysql_Python3.5(ANCONDA3)连接MYSQL数据库
  • mysql 存储过程enum 变量初始化_mysql存储过程变量使用-bug记要
  • mysql获取option的value_js:如何获取select选中的值
  • java链表 排序_Java实现单链表的快速排序和归并排序
  • java jar包 资源_java jar包资源下载
  • flash builder java_Flash Builder4.5 + BladeDS + Java 集成实例
  • java 打包成war包后 获取类路径_一个Java项目布署到weblogic里,听说weblogic会把classes目录打成jar包,怎么获取classes里文件的路径...
  • crh寄存器_STM32的寄存器控制SDA_IN()/SDA_OUT()
  • java连接openoffice_Java启动openoffice服务后拒绝连接
  • java一个方法里如何开始线程_Java并发学习第一弹:实现多线程的方法到底有几种?新线程是如何启动的?...
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • 2017年终总结、随想
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • Github访问慢解决办法
  • Invalidate和postInvalidate的区别
  • Java,console输出实时的转向GUI textbox
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • Javascript 原型链
  • java正则表式的使用
  • react-native 安卓真机环境搭建
  • React系列之 Redux 架构模式
  • 爱情 北京女病人
  • 力扣(LeetCode)965
  • 聊一聊前端的监控
  • 排序算法之--选择排序
  • 巧用 TypeScript (一)
  • 走向全栈之MongoDB的使用
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 阿里云ACE认证学习知识点梳理
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #include
  • #include到底该写在哪
  • $.ajax()
  • (003)SlickEdit Unity的补全
  • (20050108)又读《平凡的世界》
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (四)Android布局类型(线性布局LinearLayout)
  • (算法)N皇后问题
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转)重识new
  • ***通过什么方式***网吧
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .net/c# memcached 获取所有缓存键(keys)
  • .NET6 命令行启动及发布单个Exe文件