因为把公司 Mysql 一堆带 null 字段优化非空带默认值被骂

AhogeK 28天前 74

刚来一家新公司注意到数据库里新建的表有一堆 null 值的字段,想数据量大会影响索引,项目也刚开我就改了下,然后就被训了,就说别动数据库,非不非空让前端去判断(我就想是前端判断啊,但后端不也要校验,数据库只是优化查询)但我没之声 而且好多字段都是中英混用,可难受死我这强迫症了 比如父 id fid 组织类型 orglx 行政区划代码 xzqh 行政区域编码却是 adcode [捂脸.jpg]

最新回复 (100)
  • linvon 24天前
    引用 2
    快跑
  • kkkkkrua 24天前
    引用 3
    快跑
  • adjusted 24天前
    引用 4
    rails 默认一堆 allow null
  • thiscat 24天前
    引用 5
  • s0nnse 24天前
    引用 6
    决定不能信任前端的数据,跑,快跑
  • WilliamYang 24天前
    引用 7
    快跑,我说一句腊鸡
  • dallaslu 24天前
    引用 8
    很多很多年前,接触过一个产品,字段名是 a1, a2, a3 ... an 。使用的时候,比如价格字段就是 a200 ;优惠价格 a201 ;商品名 a60……
  • raaaaaar 24天前
    引用 9
    中英配合的一看就不标准啊,可以走了
  • cjw1115 24天前
    引用 10
    “比如父 id fid 组织类型 orglx 行政区划代码 xzqh 行政区域编码却是 adcode”
    这尼玛可太优秀了,面向自己编程
  • jonathanshi 24天前
    引用 11
    跑吧
  • lyoume 24天前
    引用 12
    org lx 哈哈哈 秀
  • qwe520liao 24天前
    引用 13
    NULL 值会影响索引?关于这一点我觉得还是要看场景,如果仅仅只是用空字符串或者 0 来替代 NULL 值,我觉得是没有必要的。也取决于用的什么数据库 /存储引擎。
  • dyxLike 24天前
    引用 14
    null 字段没那么严重吧, 不过这个命名方式确实...
  • javapythongo 24天前
    引用 15
    改数据库之前没有跟 learder 讨论吗?
  • GGGG430 24天前
    引用 16
    @qwe520liao
    @dyxLike
    大量 null 值相比于空字符值会占用大量空间, 导致 b+树单个叶子节点(页)能存储的方式行数减少,
    一方面会增加树高导致 io 次数增加, 也就增加了 mysql 查询耗时;
    另一方面会导致 buffer pool 在有限的内存中缓存的行数减少, 降低缓存命中率;
    最后, null 对 count 也不友好

    当然, 以上是我最近面试需要, 看了一些八股文瞎猜的
  • qwe520liao 24天前
    引用 17
    @GGGG430
    1 、NULL 值并没有比空字符串占用更多的空间,反倒是如果一个列本身用 NULL 是很自然的选择,但是强行给了一个默认值,那么这个默认值反而比 NULL 值所占用的空间更大。
    2 、关于索引,如果索引的值本身就很稀疏,那么使用默认值来替代 NULL 并不会有什么帮助( b-tree )。
    3 、还是那句话,取决于使用场景和数据库 /存储引擎,如果明确告诉你使用 NULL 就会有问题,那么这个时候才应该考虑是不是要做此类优化,提前优化是万恶之源,而且此类优化效果也是微乎其微的,只是它的不利影响被放大了。

    数据库 /存储引擎有很多选择,版本也有很多,很多网上的奇淫技巧只针对于特定的版本有效,没有必要纠结在这些小问题上,国内很多公众号、技术文章现在基本上都是广告居多,颇有点中医理论的味道。
  • Mac 24天前
    引用 18
    我对 NULL 值没这种执念,我觉得 null 挺好的,is null 和 is not null 比 empty 判断要好多了,而且我买的几家国外商业项目,也是把 null 当默认的空值在用,也没什么计较的.
  • GGGG430 24天前
    引用 19
    @qwe520liao
    首先 NULL 需要一个额外字节作为判断是否为 NULL 的标志位,
    其次您应该没接触过 mysql 规范吧, 有正规 dba 的地方, 建表时都是强制 NOT NULL DEFAULT '' 或 0 的
  • Dounx 24天前
    引用 20
    @adjusted 什么叫默认呢?
  • wuyazuofeiji 24天前
    引用 21
    我觉得你的工作方法有问题,改库这种不是应该先沟通,不管公司烂不烂
  • 楼主 AhogeK 24天前
    引用 22
    null 只是导火索 只是自己以前很少用 is null / is not null 公司里带 null 字段的有的是空串有的却是 null 的问题 就是不统一 null 是否影响索引是看场景 主要就是规范上比较难受 命名只是其中之一 公司所有的接口也不是按 RESTful 风格 统一 POST 明明用了 @RestController 却还要加个 @ResponseBody 还能在 Mapper 上看到 select * 跟大量内查询 感觉太随意了 不过看项目规模也确实没啥影响 嘿嘿
  • fiypig 24天前
    引用 23
    不要随便动已上线的数据库 , 这个你要先沟通下 ,还有一般字段创建的时候就不应该有 null 存在...
  • 楼主 AhogeK 24天前
    引用 24
    @wuyazuofeiji 哈哈哈 是的 主要是项目初 一开始让我建我建一半 结果他们又自己建好了 我又自做聪明改了 怪 哈哈哈
  • 楼主 AhogeK 24天前
    引用 25
    @fiypig 没上线,上线肯定不能的乱动,我也动不了,就是刚开始的项目 会也都没开过 字段怎么定啥的,公司直接 copy 了老项目结构吧应该
  • fiypig 24天前
    引用 26
    @AhogeK 那真的无话可说了 ,一般这属于优化这块, 不分青红皂白的训 那真的可笑了
  • bk201 24天前
    引用 27
    你这种人容易惹出事情,不要手贱。
  • 楼主 AhogeK 24天前
    引用 28
    @bk201 确实 orz
  • imn1 24天前
    引用 29
    我不担心你在这公司如何(事已至此),只担心你以后会如何
    一句话、一个动作,让全体改代码,不管对不对,这情况能活着就很好了,你要明白你不是老大啊……
  • enderftt 24天前
    引用 30
    @dallaslu 。。。我现在就是,某 ERP 产品,库里表就是 AAAAA AAAAB ACTLE 这种, 字段统一都是表后 2 位+001
    比如 AA001 AA002 LE001 LE002
  • securityCoding 24天前
    引用 31
    随便搞数据库字段容易被打哦
  • IGJacklove 24天前
    引用 32
    不管怎么样改之前都得先和大家说一声吧,万一你这改了线上出了问题算谁的?
  • yingqi7 24天前
    引用 33
    @cjw1115 会几个单词写几个,不会的拼音伺候哈哈哈哈
  • wakzz 24天前
    引用 34
    @GGGG430 Null 值需要一个比特位做标识位,也就是说 8 个 Null 才用一个字节,而 int 类型一个 0 占用 4 字节,char 类型一个空值需要 1 字节的长度位表示,Null 值才是最省空间的方案。
    另外你说的 mysql 规范,规范是人定的,很多场景下,Null 、空字符串是两种含义,技术是为了业务服务的,不能为了符合规范反而让业务更加复杂。
  • telung 24天前
    引用 35
    新公司上班,不要总觉得自己比别的同事聪明
  • Rwing 24天前
    引用 36
    这代码 走人吧
  • fkdtz 24天前
    引用 37
    公司没规范是公司的问题,你不沟通直接改就是你的问题了。
  • Lemeng 24天前
    引用 38
    好心办坏事,还是不懂的话,除非发需求
  • Lemeng 24天前
    引用 39
    @Lemeng 好心办坏事,还是不动的好
  • iloveayu 24天前
    引用 40
    不是你的屎,为什么要强吃
  • zengming00 24天前
    引用 41
    @wakzz 我觉得从程序效率的角度看 int 类型应该是预先分配了空间的,因为一个表结构如果存储的数据长度不一致会导致查找效率降低,因此实际的情况大概率是一个 int 类型和一个 bool 类型标识同时存在,共同组成来表示 int 字段的 null
  • 楼主 AhogeK 24天前
    引用 42
    不过改得是没数据的表 而且也不用动代码 也没有代码只有 mpg 生成的简单 crud 被说的话就像大家说我的那样 呜呜呜 别骂了别骂了 代码的话提议了阿里规范扫描倒是接受了 数据库改善还有待商讨,固定的几个字段上一家公司就是阿里规范的,比如表达是与否概念的字段,必须使用 is_xxx 的方式命名,但这家公司比如删除 deleted 不过也接受 创建时间跟更新时间用的 create_date 跟 udpate_date 也没事,创建者用的 creator 也没事,更新者直接来了个 updator ?数据库里字段类型我可啥都没改 比如时间用 datetime 不用 timetimestamp
  • eric96 24天前
    引用 43
    这个数据库字段命名,真的,快跑
  • ashuai 24天前
    引用 44
    这谁顶得住?赶紧跑

    被同化后你想找下份工作就难了
  • isnullstring 24天前
    引用 45
    弄默认值 其实很正常,也很应该
    但是之前没整,那就不要多手去加,吃力不讨好

    V2 和知乎也经常看到问,为什么上一任程序员看到垃圾代码不去优化
    有些代码是用时间、用钱逐个坑填上,你看到的只是最终结果
  • GGGG430 24天前
    引用 46
    @wakzz 空字符串占用空间? 你是百度的吗?
    另外, 你说规范是人定的, 我们就可以随意更改规范, 然后跟着自己的感觉来, 然后公司里面员工 A 用 null, 员工 B 用'', 这是你说的让业务更简单了?
  • optional 24天前
    引用 47
    人云亦云的孩子
  • chrosing 24天前
    引用 48
    跑~
  • redtea 24天前
    引用 49
    性能和程序运行正常哪个重要?项目还没吃透就敢动手?改了以后有没有回归测试?最关键的是为什么改之前不问一声?
  • joesonw 24天前
    引用 50
    run forest, run
  • Tumblr 24天前
    引用 51
    首先不管别的,单是你这行为,如果是在我的团队,第一我会赶紧让人把数据库密码改了,并且不能让你知道;第二把你手上的关键任务转给其他人,给你些不那么重要的东西。。。
  • dqzcwxb 24天前
    引用 52
    @wakzz #33 避免二义性比规范要重要一万倍
  • dzdh 24天前
    引用 53
    @GGGG430
    咨询一下,那允许为 NULL 是什么场景。
  • Narcissu5 24天前
    引用 54
    @wakzz 但是对于非空的字段而言,这个 1bit 就是完全多余的。如果列大部分值都是非空,NULL 就是更费空间。如果大部分字段都是 NULL,那么这个表的设计很可能有点问题
  • limuyan44 24天前
    引用 55
    良心劝告一下,就算之前的设计是一坨屎,你这行为也是大忌,可能严重到想开除的地步。
  • Fule 24天前
    引用 56
    对于是否设置为可空,我觉得关键不在于是否浪费空间,是否影响索引,使用是否方便。关键在于这个字段的**语义是否可以有、“未知”、“未设置”的含义**。

    比如“生日”这个字段,如果是在一个存放“出生婴儿”的表里,那么这个字段就应该是不可空的,因为出生婴儿必然有个出生日期(生日)这个逻辑没问题吧。

    再比如“成绩"字段, 0 和 空 是不同的概念,空代表“未知”、“未设置”,0 代表有成绩,就是 0 分。所以如果表里的成绩允许有“未知”、“未设置”这个概念的话,应该设置为可空类型。而不应设置为不可空类型,默认值 -1 之类的。
    此例中如果设置不可空默认值-1 的问题在于,数据必须在某个层级将 -1 转化为 “空”才能展示到界面,而用户在界面上未显式设置时又要将“空”设置为 -1 再保存,繁琐而现实意义不大。
  • wakzz 24天前
    引用 57
    @zengming00 不用觉得,我看过底层数据实现结构,允许 null 值的列,都有一个比特位值来表示该列的值当前是否是 null 。
  • wakzz 24天前
    引用 58
    @GGGG430 我看过 innodb 的底层文件结构,空字符串的值本身不占用空间。但例如 varchar 等变长字段,都需要一个字符长度值来让程序知道该变长字段的字节长度。这个字符长度值本身占 1 到 2 个字节,而空字符串的字符长度值占用 1 个字节。
    另外,我指的规范是人定的意思,不是说完全不用遵守规范,别非黑即白。而是按照实际的业务情况和历史原因,定义符合自己实际情况的规范。你这所指的完全没有规范就离谱了
  • wakzz 24天前
    引用 59
    @dqzcwxb 是的,业务比性能更重要,默认非 null 值尤其是数值类型的 0 值在很多场景非常容易出现歧义。
  • wakzz 24天前
    引用 60
    @Narcissu5 1bit 真的可以忽略不计,与其讨论空间浪费,不如更关注 null 值、0 值和空字符串会不会引起业务歧义的问题。
  • nthhdy 24天前
    引用 61
    我觉得吧,只要不改完一上线都挂了,都有讨论的余地
  • xupefei 24天前
    引用 62
    团队精神不足是一个大 behavioural flag,在面试中能直接枪毙了。
  • AEDaydreamer 24天前
    引用 63
    这个变量名我看着血压都已经升高了,要是我在 design table 里看到一定会找建表的人说道说道
  • killergun 24天前
    引用 64
    我上家公司单表接近一个亿的字段也是设置成 null
  • Seanfuck 24天前
    引用 65
    我记得 null 和空值也是有区别的,null 不 null 是字段设计(程序)的逻辑,空不空是数据(用户)的逻辑,这样对不对?比如一个字段既要判断用户有没有改过,同时也给用户设置为空的权力。
  • makdon 24天前
    引用 66
    新版本的 Mysql 的 null 用就是了
    如果业务上面一个字段是可空且,那就应该设置为 nullable 的列
    举个例子,有一列是采集用户的某个数据,假设是今天使用的电量吧
    那未采集的状态就是 null,采集了一度电都没有用过就是 0,这里就需要显式区分没有采集的状态
    当然你可以引入其它额外的标记位,或者引入 -1 类似的默认值
    但是这样又会在求和求平均等场景引入额外的判断条件( where cost != -1)
    最自然的做法我觉得还是让列为 nullable 就可以了

    reference: https://dev.mysql.com/doc/refman/5.7/en/innodb-row-format.html
  • wupher 24天前
    引用 67
    同意 @makdon 的意见。

    过早优化常常会带来其它的问题。除非这是张大表,有复杂的索引等等。

    从设计本身角度,更推荐该空即空。

    此外变更前与同事取得一致也是一种尊重。

    但是,汉语拼音不能忍……估计我看到也会很难受。
  • xuanbg 24天前
    引用 68
    null 都给改成非 null,然后给个默认值?换我也要破口大骂。我一个数值 null 表示无,你给我来个什么默认值? 0 还是-1 ?我告诉你,无论是 0 还是负数,在业务里面都是合法且正常的值。你给我把 null 搞成 0,实际上数据就被你破坏掉了,而且无法恢复。你说要不要骂你?
  • ReysC 24天前
    引用 69
    如果是后端来和你讨论用不用 NULL,没啥问题,只是小公司没任何文档和说明就让你开始,他们的问题;
    如果是前端和你讨论要不要用 NULL,建议立即跑路,估计这公司 CTO 都换了 N 个。
  • domodomo 24天前
    引用 70
    还不赶紧换一家,作坊式的开发公司别呆太久
  • GGGG430 24天前
    引用 71
    @wakzz 上一个回答说 char, 这个回答说 var char, 你在说啥呢, 知道"例如 varchar 等变长字段,都需要一个字符长度值来让程序知道该变长字段的字节长度"这就是看过 innodb 底层文件结构? 哪个版本的底层文件? 这和底层文件结构有啥关系, 你这不就是搜的八股文吗? 需要我给你加上 var char 的其他八股文吗, 比如 var char 还会保留末尾空格什么的吗
  • ajaxfunction 24天前
    引用 72
    如果人家程序里有很多 sql 是 is null 或 not null ,你这一改,不就导致系统奔溃了吗?
    无论代码质量咋样,起码目前已经是在跑业务的,你这一改就是人为制造 BUG 。
  • h82258652 24天前
    引用 73
    虽然楼主改表字段为非 null 确实是不妥当,但是楼主描述的其它问题更严重,没有项目文档,全是口头沟通。
    我以前就碰过一家,同一个需求,每次对方说都不一样的。这些东西应该形成文档固定下来的。
  • ihipop 24天前
    引用 74
    是否允许 null 也应该看业务需求 /数据库特性而定,,null 和非 null 的默认值的业务区别一般也是是有的,一般引擎 null 也只是不参与索引,不影响非 null 索引。
  • wakzz 24天前
    引用 75
    @GGGG430 基于的版本是 MySQL5.7 的 innodb,数据落盘后的 idb 文件。毫无实际应用价值的知识才是八股文,上面说 char 那是打快了
  • GGGG430 24天前
    引用 76
    @wakzz 反手就是一句打快了? 算了看了很多层的回答, 都是跟着感觉走, 我行我素, 以遵守规范为耻, 真是服了, 我猜很多层都不知道 b+树是什么东西, 就在这根据自己的野路子经验乱回答
  • wakzz 24天前
    引用 77
    @GGGG430 不是,建议你别把别人当傻子。网上非实名制所以吧友们想到啥说啥,论点碰撞什么的日常情况了,但这年头出来混的谁没有点东西,你猜很多层不知道 b+树就离谱了。。。笑
  • billlee 24天前
    引用 78
    不要什么都不想就禁用 NULL. 有些字段就没有合适的值来表示空值,比如用 32 位整数存 IPv4 地址,那么显然每个数值都是有意义的,显然不能用 -1 或者 0 来做空值。

    影响索引也不知道是哪来的以讹传讹的说法
  • MengiNo 24天前
    引用 79
    如果 mysql 做了几十年连 null 都要用所谓的 “规范” ban 掉的话。哪里还要去考虑什么技术、底层、原理、实现,作为一个自然人最直观的印象和感觉难道不是,要么 mysql 项目组就应该当场解散、作者出来谢罪,要么他们立刻马上连夜光速出一个 patch 把 nullable 拿掉。既然这两种情况一直都没有发生,那么至少 mysql 官方对自己的 nullable 做的还挺满意的,那既然这个 feature 没有问题,有什么不用的理由。
  • littlewing 24天前
    引用 80
    线上数据库是你能随便动的?动之前都不打个招呼!
    有时候你觉得是错的东西,或者说确实是错的,但人家写代码已经将错就错了,你一改,影响到下游多少调用方你知道吗?
  • GGGG430 24天前
    引用 81
    @wakzz 能说出“上面说 char 那是打快了”这话的人本身就是在把别人当傻子!
  • msg7086 24天前
    引用 82
    NULL 有 NULL 的用处,空值就空值的用处,本来就是不能随便替换的。
    至于你遇到的问题,这我也不太好说,但是数据库结构更改还是要做 Code review 的吧。
    Review 的时候说清楚就行了。被骂不应该。
  • fuermosi777 24天前
    引用 83
    @wuyazuofeiji 同意 20 楼的意见。
  • msg7086 24天前
    引用 84
    为避免歧义:上述空值指的是空白的默认值,比如空字符串,数字 0 等。
  • stabc 24天前
    引用 85
    问题不是改不改默认值,而是你有没有事先和团队沟通。
  • iseki 24天前
    引用 86
    数据库给你留了 null 这个功能就是拿来用的,不能不分青红皂白一律 not null 也不能全都 null
  • JerryV2 24天前
    引用 87
    别手欠,你觉得需要修改也得找负责人沟通好再改,自己直接改了这不找骂么
  • 2379920898 24天前
    引用 88
    被骂是怎么嘛?我是接受不了。大家好歹都是大学毕业
  • 2379920898 24天前
    引用 89
    他判断 not null 出错。。应该和你去沟通啊? 为什么会被骂呢??你们沟通就是挨骂?? 那以后业务问题,不更得挨骂了。赶紧跑路吧。。好的上司也很重要。这垃圾上司不要也罢
  • penll 24天前
    引用 90
    为了省这点空间,还不如不要。
    当统一数据库设计不为 null 的规范后,可以给开发人员方便许多
  • dongtingyue 24天前
    引用 91
    半桶水晃荡的典型例子,吸取经验不要不讨论就做会影响别的决定。
  • RangerWolf 24天前
    引用 92
    自作孽
  • Narcissu5 24天前
    引用 93
    @wakzz 看场景,如果你的类型是 tinyint,那么这一个位就是 12.5%的额外存储,这可不是可以忽略不计的量。

    很多时候性能就是这里一点那里一点扣下来的
  • jinhan13789991 24天前
    引用 94
    我们都是前端做输入校验,出了问题后台都怪我们前端,谁让他是领导呢。
    就当是磨练自己了
  • lsdvincent 24天前
    引用 95
    我以前也是全部不允许为 null 必须要有默认值,空字符串也行,但是这样验证就很麻烦,字段变化大,很蛋疼,后来不确定的东西全部允许 null,好极了
  • tairan2006 24天前
    引用 96
    null 对性能其实没啥影响,null 主要是有坑

    楼主你的问题在于没和别人讨论就改已有的东西,这样不太好
  • Actrace 24天前
    引用 97
    @tairan2006 赞同,看来楼主还不适应团队开发。需要多多磨合。
  • no1xsyzy 24天前
    引用 98
    NULL 和 NOT NULL 不是拿来表示字段的必须性的吗?
    咋还跟性能扯上了?

    段子:
    > 文艺程序员尝试把代码写得别人看起来方便,普通程序员尝试把代码写得自己看起来方便,二逼程序员尝试把代码写得机器看起来方便。
    > 半年以后,文艺程序员看自己代码,看不出是自己写的,但看得懂;普通程序员看自己代码,看得出是自己写的,但看不懂;二逼程序员看自己代码看了半天,破口大骂 “这是哪个 XX 写的代码?”。
  • 楼主 AhogeK 24天前
    引用 99
    @tairan2006 是的,这点昨天也有跟同事沟通。坑有,因为现在代码上直接拿数据库实体类让前端传,而前端没有统一规范,有的人也许没传 后端保存了 null 也许又传了''(意思一样却数据类型不同) 这时后台这写 sql count 不注意 null 数据就会有问题,类似还有拿 null 直接 = <> 查询的 至于说我没大家想的那么重,就说数据库不要去校验不为 null 让前端去判断(这点我挺疑惑的),不要加 not null 这个东西,不要改固定的字段名,就让我有意见先提,以后一定注意 前一家公司的数据库编写习惯确实影响了自己,不知道这家呆久了也会不会同化,现在任务也不重,还能抽空写自己的项目
  • lusi1990 24天前
    引用 100
    改没问题,提前沟通好了
  • 楼主 AhogeK 24天前
    引用 101
    @no1xsyzy 是的,是我错误的说法,想表达就是避免使用 null,使用 null 只是说很难查询优化占用额外索引空间 但也不是必须这样

    段子受教了,我还有很长的路要走 :muscle:
  • 游客
    102
返回