V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
1800x
V2EX  ›  数据库

sql 表设计问题:需索引的可选字段应该允许 null 吗?

  •  
  •   1800x · Dec 29, 2022 · 4700 views
    This topic created in 1216 days ago, the information mentioned may be changed or developed.

    比如一个用户表,中间一个字段,表示用户所属的企业。

    用户可能不属于任何企业。

    那么有两种解决方案:

    1. 企业字段允许为 null 。用户不属于企业时,企业字段为 null 。
    2. 企业字段不允许为 null ,默认 0 。用户不属于企业时,企业字段为 0 。

    再叠加一个需求,用户表的企业字段需要加索引。

    那么,应该选择哪个方案?或者有没有更好的方案?

    42 replies    2023-04-11 14:29:45 +08:00
    root000
        1
    root000  
       Dec 29, 2022
    2
    Xhack
        2
    Xhack  
       Dec 29, 2022
    is null And is not null 是不会走索引的
    isora
        3
    isora  
       Dec 29, 2022
    iseki
        4
    iseki  
       Dec 29, 2022 via Android
    依业务需求而定,数据库不能好好处理就说明该换数据库了
    Xhack
        5
    Xhack  
       Dec 29, 2022
    @Xhack 我说错了
    imv2er
        6
    imv2er  
       Dec 29, 2022
    业务逻辑设计上选 1
    有查询需求的 选 2
    securityCoding
        7
    securityCoding  
       Dec 29, 2022
    2
    tf2
        8
    tf2  
       Dec 29, 2022
    mysql 还是别用 null 了。
    CodeCodeStudy
        9
    CodeCodeStudy  
       Dec 29, 2022   ❤️ 8
    mysql 字段不使用 null 的理由

    1 、比如文章点击量加 1 ,column_name = column_name + 1 ,如果把字段设成 null ,并且插入数据时没指明 column_name = 0 ,那么+1 操作不起作用;
    2 、count(column_name)时,null 的列不包含在内,count(*)则包含 null 的列在里面
    3 、计算多列时,如 SELECT id, click1+click2 as click FROM `foo` 如果两个点击量有一个为 null ,那么相加结果就是 null
    4 、如果有比较条件,比如 where < 10 ,如果为 null 的话则不包含在内
    5 、min(column_name), max(column_name)如果字段有值,则用值比较,如果字段没有值,都是 null 的时候,则为 null

    总结:不能运算,不能比较,慢
    jarvanluo
        10
    jarvanluo  
       Dec 29, 2022
    mysql 我一般都是有默认值,不允许 null 的。text 除外。
    bthulu
        11
    bthulu  
       Dec 29, 2022
    我反正是这么来的, 所有表字段都必须设置不允许为 null.
    这样在 java 里会减少很多 NPE.
    aichunya
        12
    aichunya  
       Dec 29, 2022
    现在项目里面,除了类似'收货时间'这种具有业务意义的 date 类型的字段允许为 null 以外,其它类型字段都会设置默认值
    makelove
        13
    makelove  
       Dec 29, 2022   ❤️ 2
    别听楼上的瞎 bb ,这种情况明显用 null
    itechify
        14
    itechify  
    PRO
       Dec 29, 2022
    某些 datetime 含业务含义和 text 类型的允许 null ,其余都 not null 了
    clockwork1122
        15
    clockwork1122  
       Dec 29, 2022
    @oneisall8955 datetime 是真让我最讨厌的玩意,一般查询的场景都只需要 date 就行,数据库用 datetime 给自己增加查询难度。
    cpstar
        16
    cpstar  
       Dec 29, 2022
    @CodeCodeStudy 9# 你这些数值比较的字段,不应该把字段设置为数值类型的同时默认值是 0 ?

    oracle 的 varchar2 类型,空值即为 null 。
    meshell
        17
    meshell  
       Dec 29, 2022
    我说个其它的,在使用 ORM 的 one many 的时候 null 和 0 区别对待的。0 是找不到企业报错,null 没有企业
    yfwl
        18
    yfwl  
       Dec 29, 2022
    如果你要给这个列创建索引,那就不能 null ,因为 null 不走索引的,正常的列是允许 null 的
    SethShi
        19
    SethShi  
       Dec 29, 2022   ❤️ 4
    楼上的是不是都要更新知识了? MySQL null 列可以走索引.
    我的建议还是你用 null, 毕竟 null 和 0 还是不一样的.
    至于加不加索引和 null 不 null 无关, 取决于你的用户是否大多数有企业.
    比如你一百万用户就一百个有企业, 别加了. 如果大多数都有, 那就加
    SethShi
        20
    SethShi  
       Dec 29, 2022
    再补充一个, 取决于你的业务需求, 如果你业务代码都是.
    1. 先去查找用户 -> 然后在通过用户的企业主键去查找企业 = 不用加索引
    2. 找用户 -> join 企业 = 加索引
    3. 找这个企业下的用户 = 加索引
    Konys
        21
    Konys  
       Dec 29, 2022
    null 是可以走索引的
    cokar
        22
    cokar  
       Dec 29, 2022
    使用空字符串不是更好吗?
    zhangtest
        23
    zhangtest  
       Dec 29, 2022
    @Xhack 大哥们,你们了解下 mysql 不同版本的区别吧,别总把古董版本的特性带到目前常用的版本。
    BQsummer
        24
    BQsummer  
       Dec 29, 2022
    有些业务场景 0 和 null 就是有区别的, 咋办
    CodeCodeStudy
        25
    CodeCodeStudy  
       Dec 29, 2022
    @cpstar #16 是啊,应该设为设置型,默认值为 0 ,用 0 来表示特殊的含义,而不是 null
    9Y8lCIS38J8AlhRs
        26
    9Y8lCIS38J8AlhRs  
       Dec 29, 2022   ❤️ 1
    null 是 null, 0 是 0 ,概念首先不要乱用!!!

    假设设置成 0 , 0 多了不一样走不了索引吗。
    IvanLi127
        27
    IvanLi127  
       Dec 29, 2022   ❤️ 1
    @CodeCodeStudy 其实这个不好,我觉得更好的方案是:

    创建一个缺省公司,用来给那些不属于任何企业的用户挂名的;
    然后直接不允许这个字段为 NULL 就好了。

    这个方案就是前几年讨论 NULL 有没有必要时,一种比较优雅的方案。

    不过要是我的话,如果业务不要求对这类用户做什么操作,我肯定直接设 NULL 了 哈哈
    CodeCodeStudy
        28
    CodeCodeStudy  
       Dec 29, 2022
    @IvanLi127 #27 不用创建缺省公司来挂名,这样反而会搞复杂,企业字段直接用 0 来表示就好了
    IvanLi127
        29
    IvanLi127  
       Dec 29, 2022
    @CodeCodeStudy 其实有个问题。。。你们用 0 的前提是不用外键约束吗?如果用的话应该势必创建一个缺省公司
    JKeita
        30
    JKeita  
       Dec 29, 2022
    基本都不允许 null ,能不 null 就不 null
    CodeCodeStudy
        31
    CodeCodeStudy  
       Dec 29, 2022   ❤️ 1
    用 0 或者-1 来表示该值不存在更好的理由是保持一致的数据类型,避免 null 造成 NPE ,比如 Java 和 JavaScript 的字符串的 indexOf 的返回值是 int ,用-1 来表示找不到,而不是返回 null
    CodeCodeStudy
        32
    CodeCodeStudy  
       Dec 29, 2022
    @IvanLi127 #29 不需要外键
    CodeCodeStudy
        33
    CodeCodeStudy  
       Dec 29, 2022
    @CodeCodeStudy #9 补充一下第 4 点,如果某列允许为 null 的话,那么语句 where column_name > 10 ,where column_name < 10 ,where column_name = 10 均不能把实际值为 null 的行过滤掉,因为要用 where column_name is null ,这样就会带来不必要的麻烦
    xuanbg
        34
    xuanbg  
       Dec 29, 2022
    @seth19960929 也许他们的版本还停留在 5.5 或更早吧。。。反正我知道的 5.6 版本就已经支持 is null 走索引了。
    r4aAi04Uk2gYWU89
        35
    r4aAi04Uk2gYWU89  
       Dec 29, 2022   ❤️ 2
    按逻辑来说,null 是 null ,0 是 0 ,最好是按语意来使用。
    至于 select ... where x<y ,本来就不该带上 null 的数据。
    NoKey
        36
    NoKey  
       Dec 29, 2022
    如果公司都是用数字的话,就给一个默认公司的数字例如 0 ;如果是文字的话,就创建一个默认公司名,如:NoCompany 之类的,这样也不用纠结你这个问题了,查询起来也简单
    wiix
        37
    wiix  
       Dec 29, 2022
    null 是 null ,0 是 0 ,两者的语义完全不同,该是什么就是什么。
    把 null 用 0 表示一是使数据缺少一种表达能力,二是实际并没有减少做判断的心智负担。
    很多人讨厌 null 是因为 null pointer exception ,但有错却不能 fail fast ,带病运行更可怕。
    Outshine
        38
    Outshine  
       Dec 29, 2022   ❤️ 1
    @CodeCodeStudy #9 你这些理由对于遵循数据库设计范式的来说,完全不是问题。
    比如你说的文章点击量、需要比较大小或者参与计算的列,我找不到为 null 的场景。

    另外,mysql 早就支持 null 走索引了,知识要及时更新啊。
    iseki
        39
    iseki  
       Dec 29, 2022   ❤️ 1
    不要用 0 来表达没有,更不要自己搞出个 -1 来,这是在挖大坑;
    数据库该用 NULL 就用 NULL ,数据库不好处理,就换数据库;
    tairan2006
        40
    tairan2006  
       Dec 30, 2022
    如果大部分用户都有企业,那用啥都可以。
    如果大部分用户都没有企业,可以考虑搞个关联表,数据比较少。
    co2fe
        41
    co2fe  
       Dec 30, 2022   ❤️ 1
    为什么企业 id 要放在用户表里面,为什么不用关系表存储?
    万一你业务以后允许一个用户待在多个企业,你怎么搞。
    而且使用中间表,我觉得可以解决你这个纠结 null 还是 0 的问题。
    wi666
        42
    wi666  
       Apr 11, 2023
    选 1 ,并将企业名称字段加索引
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1444 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 203ms · UTC 16:55 · PVG 00:55 · LAX 09:55 · JFK 12:55
    ♥ Do have faith in what you're doing.