Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >空与非空:浅谈非空约束的影响

空与非空:浅谈非空约束的影响

作者头像
数据和云
发布于 2018-03-06 07:53:32
发布于 2018-03-06 07:53:32
3.3K0
举报
文章被收录于专栏:数据和云数据和云

黄玮(Fuyuncat)

资深Oracle DBA,个人网www.HelloDBA.com,致力于数据库底层技术的研究,其作品获得广大同行的高度评价.

非空约束是字段的一个重要属性。但是,很多时候,数据库表的设计人员似乎并不十分在意这个属性。最常见的现象就是,除了主键字段外,所有字段都不指定该属性。而在Oracle中,默认是允许为空。

而实际上,优化器在选择执行计划时,非空约束是一个重要的影响因素。为了说明问题,我们建立以下测试表,然后分别说明非空约束在各种情况下对执行计划和性能的影响。

谓词评估

在上面表中,字段SUBOBJECT_NAME中不存在空值,但也没有非空约束,再看以下查询,查找该字段的空值记录:

统计信息如下:

我们看到,需要对表进行全表扫描(关于索引,随后再讨论)。而如果我们加上非空约束,可以看到执行计划已经性能的变化:

统计信息如下:

注意到,在全表扫描之前,增加了一个filter,而fileter的表达式是NULL IS NOT NULL,其逻辑结果是FALSE,因此,实际上其子操作(全表扫描)并未执行。相应的,请性能数据里面CR为0。

之所以优化器会为执行计划增加这样一个filter,是因为优化器在做查询转换(Query Transformation)时,会将非空约束作为参照条件之一,对where子句的谓词做逻辑结果评估,如果评估结果为false,则会增加一个这样的filter,以避免执行一些高代价的操作。从10053跟踪文件中,可以看到这对于优化器对执行计划代价估算的影响:

非空约束对索引选择的影响

我们知道,Oracle中B*树索引中不存在空键值,即在表的数据记录中,如果索引中所有字段都为空,则该记录不会被构建到索引树中。也就是说,如果索引字段上没有非空约束,则表记录与索引记录不是完全映射的。

我们先去掉subobject_name上的非空约束,并在上面建立索引:

HELLODBA.COM>alter table t_test1 modify subobject_name null; Table altered. HELLODBA.COM>create index t_test1_subo_idx on t_test1(subobject_name) compute statistics; Index created.

执行以下语句,以获取subobject_name最小的10条记录。为了提高效率,我们希望直接从索引中直接读取前10条ROWID(索引数据已经按照subobject_name排序),然后根据ROWID获取数据记录:

我们来看执行计划

统计信息如下:

但是,查询计划和结果看,语句并没有按照设想的方式执行,得出的数据也不是我们需要的。其原因就在于,由于空值不被索引,优化器无法确认索引数据是否涵盖了所有数据记录,因而它没有选择指定索引。

我们把非空约束加上,执行计划和结果就符合我们的需求了。

我们来看执行计划

统计信息如下

非空约束对连接查询的影响

在进行数据关联时,数据集中关联字段是否存在空值也会影响优化器对执行计划的选择。我们再创建一张测试表。

再将subobject_name的非空约束去掉。

HELLODBA.COM>alter table t_test1 modify subobject_name null; Table altered.

我们通过以下语句查找t_test1中subobject_name不为table_name的数据:

统计信息如下:

可以看到,执行计划通过添加函数LNNVL和NOT EXISTS,对数据进行过滤得到结果,性能相当低。

注意:当逻辑表达是中的操作数可能为空时,LNNVL函数可以判断出该表达式的结果。

我们再把非空约束加上,

统计信息如下

可以看到执行计划通过ANTI-JOIN获取我们需要的数据,性能大为改善。

我们知道,对于空值的逻辑判断,只能通过IS NULL或IS NOT NULL进行判断,除此之外,一旦表达式中含有NULL值,结果始终为空。这也就是空值的存在不会影响JOIN或SEMI-JOIN的原因。

ANTI-JOIN,通过关联方法(NESTED-LOOP、MERGE、HASH)判断记录是否符合条件,一旦发现两边记录可以关联上,则判定不符合要求,可以放弃对一个数据集中的剩余数据的判断,因而能提高性能。而关联是同等价匹配(=)实现的,不适合空值数据。因此,关联字段可能存在空值时,无法采用ANTI-JOIN。

注意:无论是否存在空值,NOT EXISTS都可以采用ANTI-JOIN,但是它的逻辑结果与NOT IN并不等价。在以下例子中,NOT EXISTS和NOT IN的结果不相同:

统计信息如下

另外一种情况

统计信息如下:

事务回滚

HELLODBA.COM>rollback; Rollback complete.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-08-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据和云 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
见识一下SQL Server隐式转换处理的不同
隐式转换(Implicit Conversion)就像他的名字一样,是个隐秘、不容易被发现的问题,但归根结底,还是设计开发中未遵守相关的规范,或者说是不良的设计开发习惯所导致的。
bisal
2021/09/06
1.1K0
见识一下SQL Server隐式转换处理的不同
Oracle查看分析执行计划、建立索引以及SQL优化
Step2: select * from table(dbms_xplan.display)
chenchenchen
2022/03/09
4.2K0
Oracle查看分析执行计划、建立索引以及SQL优化
新增字段的一点一滴技巧
在Oracle中给表新增字段的需求,已经写了不少文章了,太多的经历告诉我们,一个简单的需求,如果不了解背后的原理,就很可能出现性能问题。
bisal
2019/12/25
1.1K0
【DB笔试面试570】在Oracle中,SQL优化在写法上有哪些常用的方法?
一般在书写SQL时需要注意哪些问题,如何书写可以提高查询的效率呢?可以从以下几个方面去考虑:
AiDBA宝典
2019/09/29
3.6K0
【DB笔试面试666】在Oracle中,高并发高负载情况下,如何给表添加字段、设置DEFAULT值
在Oracle中,在高并发、高负载的情况下,如何给表添加字段并设置DEFAULT值?
AiDBA宝典
2019/10/25
3.6K0
【云和恩墨大讲堂】谈Oracle表新增字段的影响
作者简介 刘晨,网名bisal,Oracle 10g/11g OCM,并国内首批Oracle YEP成员,博客:blog.itpub.net/bisal 很多人在做一些表设计时会留出几个reverse
数据和云
2018/03/07
2.5K0
【云和恩墨大讲堂】谈Oracle表新增字段的影响
浅谈数据库Join的实现原理
Join的实现算法有三种,分别是Nested Loops Join, Merge Join, Hash Join。 DB2、SQL Server和Oracle都是使用这三种方式,不过Oracle选择使用nested loop的条件跟SQL Server有点差别,内存管理机制跟SQL Server不一样,因此查看执行计划,Oracle中nested loops运用非常多,而merge和hash方式相对较少,SQL Server中,merge跟hash方式则是非常普遍。 一.Nested Loopsb Join
企鹅号小编
2018/02/07
5.5K0
浅谈数据库Join的实现原理
CBO 查询转换(2):反结合的NULL识别机能(null aware anti-join )
本文作者系杨昱明,现就职于甲骨文公司,从事数据库方面的技术支持。希望能通过发表文章,把一些零散的知识再整理整理。个人主页:https://blog.csdn.net/weixin_50513167,经其本人授权发布。
SQLplusDB
2022/08/19
2880
107-改进写法,让SQL执行效率更上一层楼
其中 demo101_t1(以下简称t1)和demo101_t2(以下简称t2)都是大表(几千万以上记录), 两表关联字段上重复值都比较少,如果t2表上不创建合适的索引, 这个SQL的执行效率将会是极差的(t2表做几千万次的全表扫描,估计要执行几天吧),执行计划是这样的:
老虎刘
2023/09/01
2540
107-改进写法,让SQL执行效率更上一层楼
Oracle性能优化-子查询到特殊问题
编辑手记:前面我们介绍常用的子查询优化方法,但总有一些情况时在规律之外。谨慎处理方能不掉坑。 前文回顾: 性能优化之查询转换 - 子查询类 将SQL优化做到极致 - 子查询优化 作者简介: 韩锋
数据和云
2018/03/07
1.9K0
Oracle性能优化-子查询到特殊问题
新增非空约束字段在不同版本中的演进
开发提了一个数据库变更需求,新增一字段,没有NOT NULL非空约束,但有默认值为NULL。看起来有些奇怪,因为若字段允许NULL,其默认值就是NULL,不用显示声明,可以创建一个无DEFAULT NULL的新增字段再查看desc表结构,就可以证明这点。
bisal
2019/01/29
3.2K0
OB 运维 | 一个关于 NOT IN 子查询的 SQL 优化案例
前段时间碰到一个慢 SQL,NOT IN 子查询被优化器改写成了 NESTED-LOOP ANTI JOIN,但是被驱动表全表扫描无法使用索引,执行耗时 16 秒。SQL 如下:
爱可生开源社区
2024/04/11
1800
OB 运维 | 一个关于 NOT IN 子查询的 SQL 优化案例
NULL判断对SQL的影响
看到一条SQL,很具迷惑性,原始语句包含了业务属性,因此使用模拟的操作来复现这个问题。
bisal
2021/09/06
1K0
NULL判断对SQL的影响
谈一谈in/exists , not in/not exists
这个话题应该很多人写过了,多数是在分析in/exists哪个写法效率高;not in/not exists是否等价等问题。老虎刘这里再补充点内容。
老虎刘
2022/06/22
6020
盘点MySQL慢查询的12个原因
日常开发中,我们经常会遇到数据库慢查询。那么导致数据慢查询都有哪些常见的原因呢?今天田螺哥就跟大家聊聊导致MySQL慢查询的12个常见原因,以及对应的解决方法。
捡田螺的小男孩
2023/02/24
1.5K0
盘点MySQL慢查询的12个原因
85-这些SQL调优小"技巧",你学废了吗?
下面这篇文章来自某微信公众号,作者收集了oracle 较早版本的一些SQL优化"技巧",文章标题起的很是诱人.
老虎刘
2022/06/22
1.2K0
深入浅出查询优化器
提示:公众号展示代码会自动折行,建议横屏阅读 「第一部分 查询优化器框架」 关系型数据库是一个通用系统软件,SQL作为一种结构化查询语言,用户不需要关注怎么做,只需要描述做什么,然后交由SQL引擎来处理。因为关系代数提供的等价性,同一个查询可以用不同的SQL语句描述。为防止用户所写的"不好的"SQL执行慢,这就需要查询优化器快速而准确地选择出一个效率较高的执行计划。 一般的查询优化器基于代价计算模型,包含SQL形态的变换,确定访问路径和多表连接顺序等几个重要的步骤。这些步骤被统一在一个优化器框架之内,相互
腾讯数据库技术
2021/06/02
2K0
表中已存重复数据的情况,如何增加唯一性约束?
这周某系统上线,有一个需求就是,为一张表修改唯一性约束,原因就是之前发现,由于唯一性约束设置不当,导致业务处理出现异常。
bisal
2019/01/30
2.2K0
【云和恩墨大讲堂】从执行计划洞察ORACLE优化器的“小聪明”
作者简介 黄浩 惠普 十年一剑,十年磨砺。3年通信行业,写就近3万条SQL;5年制造行业,遨游在ETL的浪潮;2年性能优化,厚积薄发自成一家 主题介绍: Oracle执行计划的另类解读:调皮的执行计划 | 诚实的执行计划 | 朴实的执行计划 说到执行计划,oracle的拥趸们自然而然会兴奋起来。在ORACLE的世界里,执行计划有着其特殊的地位,如果我们将SQL性能优化看成一个生物,那某种程度上,执行计划就是DNA。在某搜索网站中,“oracle 执行计划”关键字的搜索结果与“oracle”关键字的搜索结
数据和云
2018/03/06
1K0
【云和恩墨大讲堂】从执行计划洞察ORACLE优化器的“小聪明”
102-not in和not exists到底选哪个?这个问题有点复杂,但是结论很简单,不要被专家们带偏了。
最近在某平台学习一个关于oracle SQL优化培训课程中,听讲师在讲到not in的知识点时说:“not in的子查询是不等于的关系,不能用索引。跟in使用nested loops可以走索引的执行计划不一样”。 这个说法跟参加老师您的培训时学到的内容不太一样,到底以哪个为准呢?
老虎刘
2023/09/01
6460
102-not in和not exists到底选哪个?这个问题有点复杂,但是结论很简单,不要被专家们带偏了。
推荐阅读
相关推荐
见识一下SQL Server隐式转换处理的不同
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档