IN不等于NOT-EXISTS-MySQL-什么时候NOT (in不等于0)

教程大全 2025-07-14 05:27:12 浏览

当你想对两个表进行差分运算时,你有两种选择:使用NOT EXISTS 的子查询或者NOT IN 。后者可以说更易于编写,可以使查询方法更加明显。现代数据库系统可以优化两种执行计划从而查询到类似的结果,可以在外部和内部处理查询的相关性(我说“现代”,因为在上世纪90年代中期我已经吸取教训,当时我正在使用oracle 7.3,它没有这个功能)。

两种结构有一个很大的不同:如果子查询返回的结果为NULL,那么 NOT IN 的条件将不执行,因为 NULL不等于它或不等于其它值。但是如果你注意到这一点,它们是等价的。事实上,这些消息告诉我们,NOT IN 查询更快,人们更喜欢用它查询。

这篇文章是关于一个数据库显著变慢的情况,而空值正是罪魁祸首。

考虑以下两个可能是用来追踪点击流数据的表。由于我们跟踪匿名和注册用户, EVENTS.USER_ID是可空的。然而,当用户不空,二级指标标就会具有较高的基数。

好的,现在让我们使用这些表:从一小部分用户开始,我们想找到那些没有特定事件的用户。 使用NOT IN子句,并确保null值不出现在内部结果中,查询如下所示:

对于我的测试数据集,USERS表有100,000行,EVENTS表有10,000,000行,并且EVENTS表中大约75%的USER_ID为空。 我在我的笔记本电脑上运行这条查询,它有一个Core i7处理器,12 GB的RAM和一个SSD。

我一直运行了约2分钟,这真是…哇。

让我们用NOT EXISTS和相关的子句替换NOT IN:

这个版本运行在0.01秒,这比我预期的时间更短。

是时候比较一下执行计划了。 ***个计划来自NOT IN查询,第二个来自NOT EXISTS。

执行计划几乎相同:都是从USERS表中选择行,然后使用嵌套循环连接(“DEPENDENT SUBQUERY”)从EVENTS表中检索行。都声称使用EVENTS_USER_IDX在子查询中选择行。并且他们在每一步都估计了相似的行数。

但更仔细地查看连接类型。 NOT IN版本使用 index_subquery,而NOT EXISTS版本使用 ref。再查看ref列:NOT EXISTS版本使用了对其它列的显式引用,而NOT IN使用了一个函数。这里发生了什么?

index_subquery连接类型表示MySQL将扫描索引以查找子查询的相关行。可能是这个问题吗?我不这么认为,因为EVENTS_USER_IDX索引是“narrow”类型:它只有一列,所以引擎不应该读取大量的块来查找对应的外部查询的ID行(的确,我尝试了各种查询来测试这个索引,并且所有的运行都在几百分之一秒内)。

为了获取更多信息,我转向使用“extended”执行计划。 要查看此计划,请使用explain extended作为查询前缀,并接着使用 show warnings得到被MySQL优化器优化后的查询语句。 这是从NOT IN查询得到的(为了清晰重新格式化了):

我找不到“on EVENTS_USER_IDX Checking NULL”的解释,但我认为发生的是:优化器认为它正在执行一个IN查询,可以在结果中包含NULL; 在做出此决定时,它不考虑where子句中的空检查。 因此,它将检查(exAMIne)USER_ID为null的750万行,以及与外部查询的值匹配的几十行。 通过“检查(examine)”,我的意思是它将读取表行,然后应用不为null条件。 此外,基于运行查询所花费的时间,我认为它为外部查询中的每个候选值执行了此操作。

所以,本文的论点是:每当你想在可为空的列上使用IN或NOT IN子查询时,请重新思考并使用EXISTS或NOT EXISTS代替。


IN不等于NOT

vfp中sql语句谓词EXISTS的用法

exists 理解为包含not exists理解 不包含D项 查询条件 使用not exists 子查询条件是 成绩 小于85 “ 数据查询的结果中 不包含 成绩小于85的数据”所以 D选项正确[符合问题中成绩高于或等于 85分 的要求]C项 查询条件 中 只查询到 成绩 大于85 没有包括 85分的 数据 所以C选项不正确

don't 和not 的区别

一、陈述语气否定用法不同1、not否定陈述语气谓语动词必须借助操作词,能和not构成缩合形式的限定动词,如isnt, shouldnt, wont中的is,should, will等。 如:He is not at home. (原句有操作词is,加not)他不在家。 He will not come. (原句有操作词will,加not)他不会来。 2、dont 用于句子中没有操作词时,主语是第一、二人称和复数形式的一般现在时的陈述语气的否定,实意动词改为不带to的不定式。 主语是第三人称单数则需要加 doesnt。 一般过去时的陈述语气否定需要加didnt,例:I dont like her. (原句没有操作词,一般现在时)我不喜欢她。 He didnt do it. (原句没有操作词,一般过去时)他不会做这件事。 二、祈使语气否定用法不同1、not一般步骤祈使语气否定使用。 2、dont或do not 用于祈使语气否定,用在动词原型前 。 例如:Dont move.不要动。 Dont be stupid.不要傻。 三、非谓语动词否定的用法不同1、not可用于否定非谓语动词(如不定式、现在分词、过去分词、动名词),可直接在非谓语动词前加not。 例如:He left home early in order not to miss the first bus. (否定式不定式作目的状语)他离家早以便不耽误第一辆公交车。 Not having enough money is his main problem. (否定式动名词作主语)没有足够的钱是他最大的问题。 I found his homework not done. (否定式过去分词作宾补)我发现他的作业没有做。 2、dont或do not 不用于非谓语动词否定。

SQL中IS NOT NULL与!=NULL是等价的吗

楼上两位说 != null 不能使用的,你们动手试过吗,你们确定你真的理解他们的用法?不要误导观众! 默认情况下,推荐使用 IS NOT NULL去判断,因为SQL默认情况下对!= Null的判断会永远返回0行,但没有语法错误。 如果你一定想要使用!= Null来判断,需要加上这个语句: set ANSI_NULLS off 这时你会发现IS NOT NULL 和 != null 是等效的。

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐