请不要让 NULL 出现在表设计中_执行计划

一般程序员在设计表的时候,都喜欢对于不确认的值采用 NULL 的方式来处理,无论 ORACLE  SQL SERVER , MYSQL Postgresql, 都是这样(当然如果你用MONGODB 这样的问题就不存在了), 问题是当初设计虽然不知道一个确认的默认值,但我一般都建议,一定要给一个值。

我听到的最多的回复是,为什么,我不知道值是多少,我怎么确认一个默认值。

那我们就来看看下面这个例子。语句写的没有任何问题,并且索引也建立了,那我们就来看看这个语句的执行计划

请不要让 NULL 出现在表设计中_字段_02

在执行计划中,虽然我们没有看到脑仁疼的 table scan ,这并不是因为查询语句还好,而是因为高版本的 SQL SERVER 2016 已经优化了,TABLE SCAN 基本你看不到了,这里的主键扫描其实就已经相等于 table scan了,性能必然好不到哪里去。

请不要让 NULL 出现在表设计中_执行计划_03

在得知语句的逻辑,看似我们已经山穷水尽了,但其实问题并不是没法解决。我们只要这样干一下,我们的查询的优化器就会这样走。

请不要让 NULL 出现在表设计中_字段_04

不用说,上面的查询计划,已经比最初的执行计划要好的多了,基本上已经INDEX SEEK了,在最大方向上的变化是可以接受的了。

但我们的语句怎么改写后,会变成上面那样我们来看一下。

请不要让 NULL 出现在表设计中_默认值_05

有人在看完上面的语句,已经提出异议,你这样改,如果 endtime 和 timing 有NULL 值,结果就不对了。

好了 到此我们的文字才到了 关键点, NULL 值。NULL 不是值,他什么都不是, 字段里面有  TRUE  FALSE  ,真假, 而NULL 属于什么,不知道,不晓得,不搭嘎,NULL 值在数据库处理中,大多是要多费一道手,或者浪费存储空间的(具体的原理这里不讲了,有兴趣 BAIDU 一下即可)

那我们怎么改的,让执行计划变得比原来完美的多,我们什么都没有做,就是去掉了 NULL , 我们在数据表层面,将数据字段给予默认值,例如这个我们可以添加 时间为 1800-01-01 作为默认时间(具体根据逻辑进行设定),而既然有了默认的时间,那语句自然就已经抛弃掉了 OR 这个脑仁疼的操作。

所以,没有添加额外的索引,没有对语句进行大的变动,仅仅我们添加了两个默认值,就可以化解,OR 的操作,而且我们程序中很多的 OR 的操作均源于此,所以我极力的建议,不要让表中的字段存在 NULL ,或者最低的要求是 你的查询的 字段不要有 NULL 的情况,那么其实你的表设计已经比以前进步多了。

请不要让 NULL 出现在表设计中_字段_06