0
点赞
收藏
分享

微信扫一扫

SQL SERVER SQL 语句优化引擎探秘 之是真的吗?

古月无语 2022-06-10 阅读 105


SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_数据库

大部分数据库的语句的执行都需要SQL优化器和执行器来将SQL语句变成执行计划,在数据库中执行。网上有很多什么数据库语句的军规12条,还有什么数据库语句秘籍。但不客气的来说,里面有很多都是道听途说,或者是多年前的数据库引擎做的测试等等。SQL SERVER 在经历了多次的优化器更新换代,我们现在就使用SQL SERVER 2016 第5代数据库引擎来做一个测试,验证一下到底网上那些东西靠谱吗?


1 不给条件,SQL SERVER 会走全表扫描


的确是的,SQL SERVER 在 3代以前的SQL 优化器应该是走TABLE SCAN,但SQL SERVER 这个 5 代的优化器,到底是否还有全表扫描


SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_数据库_02


谎言一: 不给条件查询语句走TABLE SCAN -----------SQL SERVER 在不给任何条件的情况下,你只要有主键,他都不会走 TABLE SCAN,基本上SQL SERVER 这代的数据库优化器,能走主键的,就一定走主键,很少在走TABLE SCAN。 


那何时 SQL SERVER 还会走全表扫描,你的表设计时候没有主键,(也叫聚簇索引)会全表扫描,下面表没有主键索引。还是的走TABLE SCAN,可你让他如何,SQL SERVER 最基本的表设计,你都不懂,不要怪TABLE SCAN 怪你自己把。

SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_数据库_03


谎言二,有空字段,走不了索引。

网上大部分的表设计,都要求表的字段不要为NULL,因为他们说走不了索引,是吗?


谎言:在某些数据库的确是这样的,在SQL SERVER 中如果你用以下的语句去查询,绝对会走索引。


SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_sql_04


但这不是你可以以此作为借口,说我可以在查询的字段的设计中,让他有NULL值。为什么看下边

SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_sql_05

看见了吗? 又走了主键扫描,要放以前又是TABLE_SCAN, 具体为什么

这是一个很简单的逻辑问题,DBA 应该马上就明白,不明白 CALL ME 我给解释。


谎言三, IN 的性能不好,NOT IN 和 IN 的性能差不多。这绝对也是谎言,我们继续做测试。

SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_数据库_06



SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_sql_07

通过上面的两个图,对比,IN 走了索引,基本上可以等同于 where 条件 = A or  条件 = B or 条件 =C

而NOT IN 则不可以走索引,这边还是走的主键扫描,性能那是差的想当的大。


谎言四,exists 和 IN ,比较 EXISTS 的性能好,这不是谎言,这是真的,到目前为止 SQL SERVER 2016的 EXISTS 的写法 还是要比 IN 的写法效率高。当然你的相关索引的建立。


SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_字段_08


谎言五,SQL SERVER 新的SQL 执行和优化引擎,对NULL 支持良好,字段可以不在设置默认值。从下面的图看,的确是查询空值是可以的,可以走索引,没有问题哦。呵呵  在看下面一个图


SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_字段_09

马上打脸,糟糕的一塌糊涂,别急还有


SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_sql_10


下面的句子,有的程序员是这样写的


select * from [dbo].[CACONTRACT] where   [SIGNDEALER] in  ( null,'00001I73TDVW0000HAOI') 


看上去好像没有什么问题,这里我们将做一个比较


update [dbo].[CACONTRACT] set SIGNDEALER = null where id = '000000002A0060000U4D'


我们将这一行的 SIGNDEALER 设置为 NULL


然后我们查询

SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_数据库_11

SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_数据库_12


看一下,好像没有什么问题,真的没有问题吗,出了大问题,看似 IN (NULL) 这样的写法没有问题,实际上是大错特错,NULL属于没有状态的值,所以无法用一般的运算符来进行运算,上面的语句必须改为


SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_数据库_13


在看执行计划,惨不忍睹,结论就是如果你在表设计之初就让 WHERE 条件存在 NULL ,那你就的好好掂量一下,未来NULL给你带来的各种麻烦。

SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_字段_14


谎言 6 ,SQL SERVER 中的 NULL 如果使用 IS NOT  NULL ,必然无法走索引。


首先这个是真的,不是谎言,如果你胆敢使用 IS NOT NULL ,SQL SERVER 是绝对使用不了索引的,所以强烈反对 WHERE 条件的字段为NULL  这条是坐实了设计表时的硬性条款。

SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_sql_15


谎言 7  字段的大小和建立索引没有关系

SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_字段_16

我们有一个 category的字段是 VARCHAR(4000), 我们可否建立索引,现实的耳光,啪啪的。 设计字段的时候,你要多少就给多少,那种超量很多的字段,在建立索引的时候,就能打的你找不着北。另外一个很长的字段建立索引本身就有问题,各种数据库都有自己的办法解决,当然最根本的还是通过非数据库的方式来解决这样的问题 (不在此次讨论范围),卡


SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_数据库_17

谎言 8 用 JOIN 的方式一定比用 子查询的方式好


在某些环节中,JOIN 的写法是SQL SERVER 所提倡的,但不是说所有的情况都适合用 JOIN 的方式,能用INNER JOIN 的时候,非要用 LEFT JOIN , 能先缩小范围的情况下,非要先JOIN 在过滤条件,这些都不是好的SQL 语句的撰写方法,下面的图就可以看出,语句写的不一样,但执行计划是一样的。在复杂的环境,灵活的运用各种SQL 语句的写法,找到适合的才是最好的方式,而不是要限定一种SQL语句的写法。


SQL SERVER  SQL 语句优化引擎探秘 之是真的吗?_数据库_18


总结:

SQL SERVER 2016 第5代的SQL 语句执行器,只要具有最基本的数据库知识FOR SQL SERVER ,TABLE SCAN 基本不会再出现了,让TABLE SCAN 给 ORACLE  和 MYSQL 继续使用好了。

SQL SERVER 2016 中如果你在查询的时候对某个字段进行null 值的查询,则会走索引,不会不走索引。

在SQL SERVER 中 EXISTS 和 IN 相比较还是EXISTS 的写法比IN 的方法要好用,性能要高。

SQL SERVER  NULL 尽量不要用,设计表要考虑,尤其WHERE条件中的字段

根据SQL解析的逻辑,撰写适合的SQL语句,提高性能,而不是盲目相信某种固定的方式撰写的SQL语句,并固化。




举报

相关推荐

0 条评论