V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
luosuosile
V2EX  ›  问与答

请问什么时候会允许数据库字段 null

  •  
  •   luosuosile · 2018-12-28 15:21:04 +08:00 · 3310 次点击
    这是一个创建于 2164 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在设计数据库,我基本全部数据都不允许 null,然后可能为 null 的,我都给了默认值“无”用的中文,,请问这样的操作会不会无意中给自己挖了坑呢?

    29 条回复    2018-12-29 23:18:03 +08:00
    codingadog
        1
    codingadog  
       2018-12-28 15:39:13 +08:00 via iPhone   ❤️ 1
    你这字段全是 varchar ?
    真有个值就是“无”进来你咋办
    night98
        2
    night98  
       2018-12-28 15:41:06 +08:00 via Android   ❤️ 3
    很多人分不清楚“”和 null 的区别也就算了。。。还有人设置为无的。。。
    l00t
        3
    l00t  
       2018-12-28 15:41:54 +08:00
    你不如问什么时候不允许数据为 null。当你想不出什么理由不允许的时候,那就允许为 null
    mahone3297
        4
    mahone3297  
       2018-12-28 15:43:12 +08:00
    我觉得会
    luosuosile
        5
    luosuosile  
    OP
       2018-12-28 15:49:44 +08:00
    @codingadog 好像有道理
    libook
        6
    libook  
       2018-12-28 15:52:24 +08:00   ❤️ 1
    1. 以后不会把“无”当做非 null 的情况来用。
    2. 不需要判断是不是“无”值。

    业务符合上述条件的话,我觉得这么做也挺好的,前端不需要再判断是不是 null 然后重写成“无”展示出来。
    但如果前端需要判断“无”的情况,比如有个按钮,如果字段为“无”就把按钮禁用,这样用 null 可能更好一点。
    sun1991
        7
    sun1991  
       2018-12-28 15:56:18 +08:00   ❤️ 1
    一般能非 null 就不要允许 null. 随意允许 null 会给以后带来麻烦.
    null 就相当于一个缺省值. 如果什么值都不合适做缺省值的情况下, 那也只能允许 null 了.
    luosuosile
        8
    luosuosile  
    OP
       2018-12-28 15:56:24 +08:00
    @codingadog 我这里是在微信号和班级,这两个字段设置了,默认无,因为不是所有人都有微信号。暂时应该不会发生你说的情况,但是你说的情况是值得考虑的
    luosuosile
        9
    luosuosile  
    OP
       2018-12-28 15:58:30 +08:00
    @sun1991 对,我就是这么想的,所以基本都不想允许 null,但是有的字段我认为业务会出现空值的情况,我就想给个默认值,看看能不能避免掉允许 null。感觉英文和中文也没什么所谓,因为开发我肯定全是中国人,就默认了'无'
    luosuosile
        10
    luosuosile  
    OP
       2018-12-28 16:01:31 +08:00
    @libook 你说的很有用,应该不会出现这种情况,我还需要再考虑考虑
    mxalbert1996
        11
    mxalbert1996  
       2018-12-28 16:06:14 +08:00 via Android
    @l00t 我觉得如果没有特别的需要 null 的理由的话就不要允许 null,毕竟对性能也是有影响的,用空值就好
    luosuosile
        12
    luosuosile  
    OP
       2018-12-28 16:08:48 +08:00
    @mxalbert1996 嗯,允许 null 好像每行多占用一个字节,而且对这个值建索引也要多一个字节。并且有 null 值的列走索引好像更不舒服。所以数据量大了,感觉影响还是比较大
    l00t
        13
    l00t  
       2018-12-28 18:40:49 +08:00
    @mxalbert1996 #11 什么性能问题?
    l00t
        14
    l00t  
       2018-12-28 18:45:45 +08:00   ❤️ 1
    @luosuosile #12 你在说什么鬼……不同数据库有不同的处理方式,就是同一个数据库比如 MySQL,不同的引擎也有不同的做法。因为性能调优之类的原因而做取舍不是不可以,但要建立在你确定知道你在做什么的前提下。如果不清楚不知道,那就不要想太多,尽量使用和发挥特性来满足业务需求才是优先。
    mmdsun
        15
    mmdsun  
       2018-12-28 18:54:10 +08:00 via Android
    我对网上传闻表示质疑。一直以来都有说 MySQL 不适合用 null 用“”来代替。

    mysql 文档上有写对 is null 查询有额外的优化。


    那么 where 字段=“”这样真的比 where 字段 is null 查询要快??

    如果一个表的字段,有 10%数据的可能是空的。用“”还是 null 好?,如果 80%都为空:是用“”还是用 null 好?
    mmdsun
        16
    mmdsun  
       2018-12-28 18:56:19 +08:00 via Android
    如果是数值呢?楼主是默认返回 0 么?

    假如字段是考试成绩。
    0=0 分
    null 等于没有考试
    还是有区别的
    msg7086
        17
    msg7086  
       2018-12-28 19:00:33 +08:00   ❤️ 1
    @luosuosile NULL 和'NULL'是两回事啊。
    微信号不允许中文这也就算了,如果某个字段里「无」是合法值怎么办。
    而且假如你的业务要求微信号需要唯一索引怎么办?你给每个无都加上小尾巴吗。

    真要说性能调优,请拿实际性能测试说话。这个索引会产生多大的性能损失,修改后是否有性能改善,改善有多大,是否值得牺牲数据正确性来换取这个性能调节。

    NULL 原本的用途是表示一个值未提供。对于微信号这种字段,如果用户没有填写,那么 NULL 就是最适合的表达了。空字符串、默认值等实现方法一样有上面的唯一索引冲突问题。

    如果理解上有困难,可以换个思路去理解:NULL 不是一个值,NULL 是没有值,NULL 不是缺省值。
    momocraft
        18
    momocraft  
       2018-12-28 19:03:24 +08:00   ❤️ 1
    "无" 还不够坑,还可以根据用户 locale 返回 "冒得" "nil" "某" 等
    lanterboy
        19
    lanterboy  
       2018-12-28 19:23:35 +08:00
    @momocraft #18 你是魔鬼吗
    passerbytiny
        20
    passerbytiny  
       2018-12-28 19:26:50 +08:00 via Android
    Boolean.true, Boolean.false, <Boolean>null,是 Boolean 变量可能有的三个值,请问楼主此时怎么表示第三个值。
    再来个贴近现实的,楼主准备怎么表示一个人一次考试是否及格的全部情况—及格、不及格、没考试
    rogwan
        21
    rogwan  
       2018-12-28 19:47:28 +08:00 via iPhone   ❤️ 1
    没有必要矫枉过正。这个值本来可能有,可能没有,不用找一个符号去代表没有,Null 自己代表没有完全没有问题。
    Leigg
        22
    Leigg  
       2018-12-29 09:04:56 +08:00 via iPhone
    一般可以用空串表示 null,除非场景特殊,我认为你的场景是可以这么做的,微信号为空串不就代表没有提供吗。
    luosuosile
        23
    luosuosile  
    OP
       2018-12-29 09:49:17 +08:00
    昨天直到下班都没多少回复,今天一上班看到 16 条很是高兴,V2 确实给了我一个解惑的平台,这么热心的 v 友,百度是找不到的,google 又太吃力了。
    luosuosile
        24
    luosuosile  
    OP
       2018-12-29 10:12:18 +08:00
    前提还是说明一下吧,我是个一年菜鸡,这是我第一次主力设计数据库,虽然产品要求其实不是很高,但我认为是个宝贵经验,想要尽量做到尽善尽美。
    那么我先来解释一下我为什么会这么做,又为什么会产生疑问,事先说明一下,我这个做法不是百度得来的,也不知道有人用“”来代替 null,这种做法快或者不快。“”,和 null 我的理解仅止于空字符串和没有插入数据,能听到大家的理解我也很开心。

    我会这么做,是因为对《高性能 mysql 》这本书稍微认真的读了一遍,于是参考这本书进行数据库设计。但是苦于没有经验,理解仅止于表面,而不知道实际是怎样的,
    我并不是想拿书名,背书来反驳各位,只是想解释一下我为什么这么做,不想大家觉得我是个百度就完了的 boy。
    里面有一个简单的原则:
    “尽量避免 null ”,实际上内容不翻书我也记不得,只记得作者确实很强调,如果不是真的需要 null,就不要允许 null。
    刚好之前帮朋友进行了下数据库优化,虽然是菜鸡互啄,但效果还是有的,从 4 分钟变成了 3 分钟,大概设计的人是个更大的菜鸡,因为他的公司是个外包公司。。这里主要时看到他的语句中有大量的 isNull,和对“”的判断。觉得很难受,在想自己能不能尽量避免这种情况。
    刚好业务就来了,未必能传值进来,与其放着 null,我在想放一个别的可能会更好,所以就有了这个问题。至于唯一索引
    我确实没有想到,学习到了。


    还有,对于这种优化有没有必要的疑问,诚然,为了提升那么一点性能而牺牲业务是很愚蠢的,而且我也不认为自己的数据量可能大到需要如此刁钻的优化,甚至随便搞搞都够用,只是我想做到尽量都能考虑到,,因为问题就在那里,放着我觉得不舒服。
    luosuosile
        25
    luosuosile  
    OP
       2018-12-29 10:14:22 +08:00
    还有对于上来就嘲讽的,我就是不懂才来提问的,你嘲笑一个本来就不懂的人不懂他的问题,我不知道有什么意思。
    回复框右下角不是有“请尽量让自己的回复能够对别人有帮助吗”。
    luosuosile
        26
    luosuosile  
    OP
       2018-12-29 10:28:24 +08:00
    @msg7086 你说的有道理,我觉得很有帮助。
    不如说,我想知道如果一个表非常大,性能要求高的时候,设计表对这个是否允许 null 是怎么处理的。
    我的确知道自己的业务没有必要这么做。
    确实如果对多种数据类型想表达这种思想,找不到一个统一的符号,分别给一个符号又太蠢,允许 null 确实是很好的做法。
    msg7086
        27
    msg7086  
       2018-12-29 11:07:34 +08:00
    @luosuosile 如果是我来设计的话,语义正确性我是会放在首位的。
    如果语义正确导致性能下降,那么我宁愿考虑从其他地方对数据库进行优化。
    比如你已知某个查询会花掉三五分钟,那么首先这个查询本身能不能优化?能不能拆分成多句简单句?能不能把负载压力从数据库转嫁到应用程序端(以方便横向扩展)?能不能把查询的结果缓存进 Memcache / Redis ?
    而且一个简单的 NULL (旗标)变成一个复杂的值(字符串),到底对性能有正面影响还是负面影响?直觉告诉我,这样的索引效率可能会更低。我一时想不出有哪个查询在这样修改以后会变快的。如果你有合适的查询语句的话,不妨贴出来大家一起研究一下。
    micean
        28
    micean  
       2018-12-29 13:21:09 +08:00
    肯定挖坑,只要空字符串就行了
    l00t
        29
    l00t  
       2018-12-29 23:18:03 +08:00
    @luosuosile #26 说到性能就要说明具体的操作环境了。比如你用的是什么数据库(从你不经意的透露我推测是 MySQL ),什么引擎,表的数据量大小,查询的数据量一般在多少,需求的响应时间大概是什么级别。《高性能 mysql 》那本书我记得它紧接着就说把 NULL 列改为 NOT NULL 带来的性能提升很小吧? 另外说实话,它的这段描述到底对不对我都是很怀疑的…… 要考虑它的时代背景。你比如你说允许为 NULL 的记录占用空间真的会多些? InnoDb 里明显不成立嘛。假如你编码为 UTF8,一个“无” 占 4 个字节(3 + 1),一个 null 只占一字节,而且还能和其他 7 个 null 共享。

    带 null 的列,我见过的主要顾虑大多是出于开发时对 null 判断的处理上的。很多人写着写着会忘了 is not null, is null 这种事,而一律用 大于小于等于,以至于踩到坑。另外就是玄学,“我也不知道为什么,反正不要用就是了”。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1116 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:46 · PVG 07:46 · LAX 15:46 · JFK 18:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.