怎样介绍自己做的网站烟台网站建设服务
怎样介绍自己做的网站,烟台网站建设服务,网站建设 教学视频,网站建设和优化的好处原文:在SQL Server中为什么不建议使用Not In子查询在SQL Server中#xff0c;子查询可以分为相关子查询和无关子查询#xff0c;对于无关子查询来说#xff0c;Not In子句比较常见#xff0c;但Not In潜在会带来下面两种问题#xff1a; 结果不准确 查询性能低下 下面我们…原文:在SQL Server中为什么不建议使用Not In子查询 在SQL Server中子查询可以分为相关子查询和无关子查询对于无关子查询来说Not In子句比较常见但Not In潜在会带来下面两种问题 结果不准确 查询性能低下 下面我们来看一下为什么尽量不使用Not In子句。 结果不准确问题 在SQL Server中Null值并不是一个值而是表示特定含义其所表示的含义是“Unknow”可以理解为未定义或者未知因此任何与Null值进行比对的二元操作符结果一定为Null包括Null值本身。而在SQL Server中Null值的含义转换为Bool类型的结果为False。让我们来看一个简单的例子如图1所示。 图1.Null值与任何值进行对比结果都为Null SQL Server提供了“IS”操作符与Null值做对比用于衡量某个值是否为Null。 那么Not In 的问题在哪呢如图2所示。 图2.Not In产生不准确的值 在图2中条件3不属于Not In后面列表的任意一个该查询却不返回任何值与预期的结果不同那么具体原因就是Not In子句对于Null值的处理在SQL Server中图2中所示的Not In子句其实可以等价转换为如图3所示的查询。 图3.对于Not In子句来说可以进行等价转换 在图3中可以看到Not In可以转换为条件对于每个值进行不等比对并用逻辑与连接起来而前面提到过Null值与任意其他值做比较时结果永远为Null在Where条件中也就是False因此3null就会导致不返回任何行导致Not In子句产生的结果在意料之外。 因此Not In子句如果来自于某个表或者列表很长其中大量值中即使存在一个Null值也会导致最终结果不会返回任何数据。 解决办法 解决办法就是不使用Not In而使用Not Exists作为替代。Exists的操作符不会返回Null只会根据子查询中的每一行决定返回True或者False当遇到Null值时只会返回False而不会由某个Null值导致整个子查询表达式为Null。对于图2中所示的查询我们可以改写为子查询如图4所示。 图4.Not Exists可以正确返回结果 Not In导致的查询性能低下 前面我们可以看出Not In的主要问题是由于对Null值的处理问题所导致那么对Null值的处理究竟为什么会导致性能问题让我们来看图5的示例。图5中我们使用了Adventurework示例数据库并为了演示目的将SalesOrderDetail表的ProductId的定义由Not Null改为Null此时我们进行一个简单的Not In查询。如图5所示。 图5.Not In的执行计划 在图5中我们看到一个Row Count Spool操作符该操作符用于确认ProductId列中是否有Null值过程是对比总行数和非Null行数不想等则为有Null值虽然我们知道该列中没有Null值但由于列定义是允许Null的因此SQL Server必须进行额外的确认而该操作符占用了接近一半的查询成本。因此我们对比Not Exists如图6所示。 图6.Not In Vs Not Exists 由图6可以看出Not In的执行成本几乎是Not Exists的3倍仅仅是由于SQL Server需要确认允许Null列中是否存在Null。根据图3中Not In的等价形式我们完全可以将Not In转换为等价的Not Exist形式如图7所示。 图7.Not In转换为Not Exists 我们来对比图7和其等价Not In查询的成本如图8所示。 图8.成本上完全等价 因此我们可以看到Not In需要额外的步骤处理Null值上述情况是仅仅在SalesOrderDetail表中的ProductId列定义为允许Null如果我们将SalesOrderHeader的SalesOrderID列也定义为允许Null时会发现SQL Server还需要额外的成本确认该列上是否有Null值。如图9所示。 图9.SQL Server通过加入Left Anti Semi Join操作符解决列允许Null的问题 此时Not In对应的等价Not Exist形式变为如代码清单1所示。 SELECT * FROM Sales.SalesOrderHeader a WHERE NOT EXISTS ( SELECT * FROM Sales.SalesOrderDetail b WHERE a.SalesOrderID b.ProductID ) AND NOT EXISTS ( ( SELECT * FROM Sales.SalesOrderDetail b WHERE b.ProductID IS NULL ) ) AND NOT EXISTS ( SELECT 1 FROM ( SELECT * FROM Sales.SalesOrderHeader ) AS c WHERE c.SalesOrderID IS NULL ) 代码清单1.当连接列两列定义都允许Null时Not In等价的Not Exists形式 此时我们简单对比Not In和Not Exists的IO情况如图10所示。 图10.Not In吃掉很高的IO 小结 本文阐述了Not In 的实现原理以及所带来的数据不一致和性能问题在写查询时尽量避免使用Not In而转换为本文提供的Not Exists等价形式将会减少很多麻烦。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/89897.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!