V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wh469012917
V2EX  ›  程序员

为什么很多人连基础的 SQL 都写不好,却开口闭口就是缓存架构分布式?

  •  5
     
  •   wh469012917 · 53 天前 · 13458 次点击
    这是一个创建于 53 天前的主题,其中的信息可能已经有所发展或是发生改变。

    说下情况,我们公司同个部门的好几个同事,连个基础的 SQL 都写不好,代码中一堆数据库 N+1 的问题,连个 WHERE IN 查询都不会用,涉及到批量查询,都是遍历然后一条条的去跑 SQL,同一个方法重复查询了好几次,数据库设计更是不行,外键都是用逗号分隔拼接成字符串,然后保存到主表上。

    正因为 SQL 写的烂,所以接口性能很差劲,但是他们好像都不在意这些 IO 方面的优化,整天在想着怎么优化语言性能,比如反射、JSON 序列化、语言基础库的性能;要么就是上集群、加缓存,然后又没有任何设计模式,直接业务代码中强硬加入缓存读写,就算是缓存也是先从缓存读出数据,然后遍历一条条去数据库再查出来,性能更差了

    其实整体项目量不大,好好写好 SQL,基本上能搞定 90% 的性能问题了,大部分的开发经验也都好几年了,不至于这种基础知识点不懂,可为啥就是不重视 SQL 性能

    206 条回复    2021-09-11 20:47:45 +08:00
    1  2  3  
    infun
        1
    infun   53 天前
    可能是培训的
    charlie21
        2
    charlie21   53 天前 via iPhone   ❤️ 2
    方便搞大清洗,具体请 v 站搜大清洗
    felixcode
        3
    felixcode   53 天前 via Android
    他们理解的没有好好写 SQL,只是认为自己把逻辑和负载都放程序代码里了,SQL 不值得优化。
    却没意识到 SQL 能力的孱弱已经是瓶颈。
    wh469012917
        4
    wh469012917   53 天前
    甚至在优化 json 序列化、网络传输包、语言反射等性能,但是代码中 sql 查询一大堆的 n+1,那些优化等半死,才提升了几十毫秒的性能,大头全被 sql 占去了
    palfortime
        5
    palfortime   53 天前 via Android
    可能考虑以后量大的时候能够容易扩展? in 的值多了也不走索引。
    wh469012917
        6
    wh469012917   53 天前
    @infun 也不至于,都是工作了四五年了,再怎么培训的也不至于这么不行,其他缓存队列分布式,说的头头是道
    wh469012917
        7
    wh469012917   53 天前
    @palfortime 就算 in 能这样解释,那 n+1 呢?这个可是妥妥的拉性能的查询
    Acoffice
        8
    Acoffice   53 天前   ❤️ 6
    因为公司不在乎,领导不在乎,拿钱干活,至于活干的好不好,没人在乎啊!
    最重要的是 很多人只是来挣工资的,至于自己的技术,凑合就行啊!
    ---
    还有的是公司文化,得 有人造锅,有人甩锅,有人接锅 才能形成闭环,利益最大化!
    wh469012917
        9
    wh469012917   53 天前
    @Acoffice 我倒是更认同你这个说法
    GiantHard
        10
    GiantHard   53 天前
    Code Review 的时候提醒一下应该会改吧
    yanzhiling2001
        11
    yanzhiling2001   53 天前   ❤️ 1
    别说了别说了,感觉都是再说我。

    大佬指点一下该怎么优化 sql,或者 怎么发现 sql 执行时间这个问题。

    写 sql 从来都是随心所欲,拿出来数据就行了的。
    RRRoger
        12
    RRRoger   53 天前   ❤️ 4
    i cannot agree more
    wh469012917
        13
    wh469012917   53 天前 via iPhone
    @GiantHard 木有 code review
    opengps
        14
    opengps   53 天前   ❤️ 2
    能被作为典型培训的教材,普遍都是分布式集群等环境下处理简单业务的模式。模式本身没问题,只是确实让一帮没理解透业务的人充了门面
    wm5d8b
        15
    wm5d8b   53 天前 via Android
    @wh469012917 培训的是有这种情况,工作多少年都一样,他们完全没有这方面的认知。另外,说的头头是道,不代表实际会用,许多人都是只会背诵
    wangbenjun5
        16
    wangbenjun5   53 天前
    循环查 sql,确实致命,哈哈,不是懒就是真蠢!!!
    xinJang
        17
    xinJang   53 天前
    涉及到批量查询,都是遍历然后一条条的去跑 SQL
    xinJang
        18
    xinJang   53 天前
    @xinJang 这句没看明白。是查出 list 然后批量 update 或 delete ?
    wh469012917
        19
    wh469012917   53 天前
    @xinJang 你想多了,举个这个的需求:在一个用户列表里,显示用户发表的动态数量;他们的实现就是先把用户列表取出来,然后遍历这个 userList,然后取其中的用户 ID,再一条条 SQL 去 count 用户的动态数量,在组装到用户实体上
    wh469012917
        20
    wh469012917   53 天前
    @wangbenjun5 我有委婉提过这个问题,他们说 JOIN 太难用了
    wh469012917
        21
    wh469012917   53 天前   ❤️ 1
    @opengps 对的,分布式微服务架构,是一把利剑,但其实大部分中小应用都用不到,单体应用一把梭了
    wh469012917
        22
    wh469012917   53 天前
    @yanzhiling2001 可以去学习一下 mysql,都说 IO 是 Web 应用的性能瓶颈,而 SQL 查询是 IO 最重的地方,优化一条慢查询,比你做什么集群分布式都好用
    xinJang
        23
    xinJang   53 天前
    @wh469012917 这种应该直接关联表查询,子查询 count 吧
    wh469012917
        24
    wh469012917   53 天前
    @xinJang 对的,关联查询一条 SQL 就能搞定了,按照遍历的方式,列表越长执行的 SQL 数越多
    wangyzj
        25
    wangyzj   53 天前
    会做不如会叫
    叫得好听肯定更容易被喜欢
    xinJang
        26
    xinJang   53 天前
    @wh469012917 这里我想引申一个问题。就是最近有个项目用得 spring boot,orm 框架是 jpa 。这里关联查询出来的数据,关联表的字段没法映射到实体类,网上没找到好的解决方式,这种有遇过么?
    final7genesis
        27
    final7genesis   53 天前   ❤️ 3
    @wh469012917 第一次就把系统做好了,没有优化空间,系统上线没问题,然后老板把研发开了,留下几个运维人员
    zhuzhibin
        28
    zhuzhibin   53 天前
    习惯就好 动不动就分布式、高并发、微服务 我身边也很多这种人,他们可能仅仅是看了一篇文章,就开始吹,各种熟悉 xxx,问起来或者动起手来,就尬住。
    lizhenda
        29
    lizhenda   53 天前
    其实就是不会不重视不想学
    wh469012917
        30
    wh469012917   53 天前
    @zhuzhibin 我们每天访问量不大,也就百万级别,而且并发不高,写好 sql 其实可以解决大部分问题了
    wh469012917
        31
    wh469012917   53 天前
    @lizhenda 差不多这个意思,学起来不难,就是不想去学,能用就行
    stach
        32
    stach   53 天前
    楼主说的有道理, 不过单看你举的那个例子, 如果 `用户发表的动态数量` 这个表很大的话 (上千万), 你同事做的并没有问题.
    stach
        33
    stach   53 天前
    更好的做法是, 设计一张独立的用户统计表, 把 `动态数` 存起来, 单独维护, 这样就可以批量查询用户的动态数量了.
    Latin
        34
    Latin   53 天前
    同事:你在教我做事啊! (狗头
    offswitch
        35
    offswitch   53 天前
    @wh469012917 join 确实难用,就你说的这个,list 估计也不大,像 count 可以优化一下,改成读缓存。
    summerLast
        36
    summerLast   53 天前
    @xinJang @Formula 看看这个注解
    chendy
        37
    chendy   53 天前
    因为这种操作更容易让外人觉得自己很厉害,更容易找到吹逼的资本然后找下家
    深耕业务各种优化也可以,但是要注意自己做记录做统计,因为不懂的人真的不知道你在干啥
    thtznet
        38
    thtznet   53 天前
    国内风气如此,不加点新名词怎么显得高级(华为别骂我)? SQL 用来几十年太成熟了,爆点不好搞出来嘛。
    wh469012917
        39
    wh469012917   53 天前
    @stach 我是为了避嫌,所以假设了一个业务场景,而且下文也说了,数量级不大,单表最多也不过 2000w,过早的优化是万恶之源,只要写好 sql,基本上 ok
    wh469012917
        40
    wh469012917   53 天前
    @offswitch join 不难用,只是心里害怕罢了;读缓存如何保证数据一致性呢?
    wh469012917
        41
    wh469012917   53 天前   ❤️ 1
    @thtznet 这个倒也是,国内风气确实也不大行,我上一家公司,一个没啥访问量的公司内部系统,都得用上全套的微服务架构
    zxCoder
        42
    zxCoder   53 天前
    正常,我还没毕业呢,找工作看的也都是分布式架构啥的,写 SQL 这种平时自己小项目也不会在意,面试也不怎么问
    MoYi123
        43
    MoYi123   53 天前   ❤️ 1
    确实,我也碰到过有些人,4 种事务隔离级别倒背如流,写 sql 要把某个数字-1 的时候,要先弄个 redis 锁,select 出来再 update 。
    wh469012917
        44
    wh469012917   53 天前
    @zxCoder 不积跬步,无以至千里
    dcoder
        45
    dcoder   53 天前   ❤️ 8
    1. 因为精通 SQL 对跳槽, 尤其是互联网高薪的职位, 好处很少
    大家都是面向简历编程 XD

    2. SQL 确实表现力很弱, 很多时候用着别扭. join, 甚至自带的外键什么的, 搞分布式挺忌讳的.
    其实我觉得 SQL 能流行, 就是整个行业之前把科技树点歪了... 这个说来就话长了... 但是从目前大环境看, SQL 用起来方便的时候, 该用还是得认真学, 正确地使用

    3. SQL transaction VS distributed lock (Redis)
    使用在 1 个 db, 1 个 service 时候, SQL transaction 好用
    逻辑稍微复杂点, 跨 db/services 的时候, 还真得用 distributed lock
    jtwor
        46
    jtwor   53 天前
    中间件工程师。。
    xx6412223
        47
    xx6412223   53 天前
    太多了,
    分布式锁:不管运维,成本,稳定性,就要上 zookeeper 啥的。用 sql 写一个排他锁不会,数据库乐观锁没听过
    nekoyaki
        48
    nekoyaki   53 天前
    点进来之前我以为楼主指的 sql 写不好指的是不用存储过程 /触发器 /各种偏门函数 /复杂 sql 联查,还想说这些邪门歪道到了大数据量的生产环境以后再想优化就是受罪

    结果点进来之后一看,哦连 n+1querys 和 where in 都不会用,那就确实是最基本的能力问题了……
    daguaochengtang
        49
    daguaochengtang   53 天前   ❤️ 1
    这就像现在前端原生 js 基础都没搞懂呢,满口都是 vue 源码
    calming
        50
    calming   53 天前
    太畸形了,面试都要问分布式啥的,基本上平时都随便写写业务狂背八股文不就这个下场嘛
    offswitch
        51
    offswitch   53 天前
    @wh469012917 不是我写不好,这上面的人对 mysql 了解估计还没我深,写 join 很蛋疼,要处理起来太麻烦。
    wxy1991
        52
    wxy1991   53 天前
    你这什么公司啊,我工作 5 、6 年都没见过 n+1 逻辑的代码,连用外键的都少,刚看到帖子的时候我还纳闷 n+1 是什么问题,感觉稍微脑袋正常的人都写不出来这种代码吧,而且像很多公司都是禁止使用外键的。
    jsjjdzg
        53
    jsjjdzg   53 天前
    惭愧,SQL 写的不太好,有次面试喜欢的公司因为 SQL 不行被 Pass 了 = =
    silk
        54
    silk   53 天前
    @daguaochengtang 毕竟面试只问算法
    jsjjdzg
        55
    jsjjdzg   53 天前
    自己练习的也少,公司的要求也是 SQL 不准使用复杂 SQL,能业务处理的就业务处理
    xuanbg
        56
    xuanbg   53 天前   ❤️ 1
    基本功不行的,遇到问题只会照抄。而且不懂得变通,解决问题的手段往往极其拙劣。
    wh469012917
        57
    wh469012917   53 天前
    @dcoder sql 手写难受,那用个好用的 orm 可以解决大部分 sql 问题了。就比如 laravel 的 orm,基本上都不用手写 sql 了,但是虽然不用自己写,但是原理还是要懂,至少最简单的 in 查询要会吧
    wh469012917
        58
    wh469012917   53 天前
    @calming 面试问不问是一回事,至少自己要懂这些东西吧,sql 算是基本功了
    neoblackcap
        59
    neoblackcap   53 天前
    @wh469012917 join 的问题在于你把业务压在数据库层面上了,这个看规模。有的公司倾向于在代码层面上面解决这个问题。用不用 Join 得看情况。因为如果换底层了,count 的方式可能比较好改,join 的方式就不见得那么好改了(比如加缓存或者换数据库存这部分的信息)。
    wh469012917
        60
    wh469012917   53 天前
    @wxy1991 多了去了,可能你们也存在 n+1 的问题,只是没发现而已; google 搜索一下 sql n+1,这个在使用 orm 的时候比较经常遇到
    wh469012917
        61
    wh469012917   53 天前
    @neoblackcap 这样说其实也对,也可以把 join 拆出来,分开查询也可以,但是 n+1 以及 in 查询,这些算是基本功了
    wh469012917
        62
    wh469012917   53 天前
    @daguaochengtang 正常,瞎说又不用有什么成本
    kemistep
        63
    kemistep   53 天前
    sql 写的好不好,让他们写个次日留存,第 2 日留存,第 3 日留存,就知道能力了;
    jtwor
        64
    jtwor   53 天前
    in 很多都是临时表查出 id 然后再用 id 去 in 查询这样就走 range 了好像比 index 还快。join 要看分库分表决策吧。确实现在很多都用 orm,直接弱化很多人的 sql 能力。
    wh469012917
        65
    wh469012917   53 天前
    @jtwor 对,这样也确实比较建议;但是奈何不会啊,都是遍历这个 id list,然后一条条 where id = ? 这样去查询,妥妥的拉低性能
    ipwx
        66
    ipwx   53 天前
    @wh469012917 所以你可以问问你的同事,有没有听说过临时表 TEMPORARY TABLE,知不知道 mysql temporary table ON HEAP 是内存表很快。

    ----

    你看,如果不知道临时表这个功能,那你除了 for loop 还有啥办法?当年我不知道临时表的时候,我为了不那么愚蠢的 for loop,最开始我是给 id 切成一个 batch 一个 batch 然后 for loop 的。为了能用 prepared statement 我还强行填满最后一个 batch 然后靠 null 来区分是不是真的有数据。。。
    lithiumii
        67
    lithiumii   53 天前 via Android
    给他们发个只连生产数据库的 Tableau,让他们做各种统计报表,一个月下来保证个个都是随手三百行 sql 的大佬(于此同时数据库被平均时长半小时的慢查询淹没,用户没一个能在上班时间使用的
    ipwx
        68
    ipwx   53 天前
    @wh469012917 你别笑。当年我很在乎性能,可是不知道 temporary table 就是不知道。我都用上 batch + null 判断来“想办法优化性能了”(大概确实能优化一点吧)
    wh469012917
        69
    wh469012917   53 天前
    @lithiumii 线上很多接口超时的,都是 sql 查询太多了
    roundgis
        70
    roundgis   53 天前 via Android
    n+1 要看情況,如果可以命中 cache

    還好了

    特別是那種 select by id 的簡單查詢
    pocarisweat
        71
    pocarisweat   53 天前
    类似 FaceBook 到今天都在大量使用自己魔改的 PHP,为什么不用 Go 重写呢?说明 FaceBook 的技术眼界已经被 Bilibili 吊打了 🐶
    wh469012917
        72
    wh469012917   53 天前
    @roundgis 对的,如果有 cache 确实还算 ok,但是关键没有 cache 也这么搞
    dcoder
        73
    dcoder   53 天前
    @wh469012917 以前写 Django 时用 ORM 很多. 后来写 Go 多了, 都是直接写 SQL 了. 感觉各有个的好.
    wh469012917
        74
    wh469012917   53 天前
    @dcoder 嗯对的,没有哪个更好,选个合适的即可
    CodeCodeStudy
        75
    CodeCodeStudy   53 天前   ❤️ 1
    面向面试编程,现在的面试动不动就是分布式、大数据什么的,多吹一吹这些东西能拿高工资,因为面试官特别是当了管理的面试官,大多都是杂而不精,每个东西都懂一点,所以叫他们深入 SQL 优化,他们也不知道,更不知道怎么去问人,通常都是笼统地问怎么优化数据库
    muzuiget
        76
    muzuiget   53 天前
    开讲有话:面试造航母,工作拧螺丝。
    wh469012917
        77
    wh469012917   53 天前
    @CodeCodeStudy 话这么说,但是开发自己至少要懂吧,这些算是基本功了
    sagaxu
        78
    sagaxu   53 天前 via Android
    我司平台架构组大佬,搭建的配 key value 置中心,key 在 db 里面是没有索引的,每次落到 db 都是全表遍历
    JudyHal
        79
    JudyHal   53 天前
    一般只有写 Java 的人才会有这个特点
    qinghou
        80
    qinghou   53 天前
    统计慢查询,挂在名字上,自动就能学会优化 SQL 。

    缓存队列分布式如果真能说的“头头是道”,mysql+SQL 相对来说简单很多。
    wangkun025
        81
    wangkun025   53 天前
    以为是说我🥶。
    xz410236056
        82
    xz410236056   53 天前
    “正因为 SQL 写的烂,所以接口性能很差劲,但是他们好像都不在意这些 IO 方面的优化”
    虽然他们很垃圾。但是这些工作不是 DBA 的事儿吗
    xz410236056
        83
    xz410236056   53 天前
    @felixcode 这么看平时是没有做性能分析的,用分析工具很容易看到哪里是瓶颈
    vjnjc
        84
    vjnjc   53 天前
    占楼问一道 sql 面试题,想出,但设计不好。。
    play78
        85
    play78   53 天前
    @lithiumii 确实,以前感觉 orm 特别好用,不用写 sql 。直到我负责公司运营数据后。各种按月按年各种汇总数据分析。才感觉写 sql 是最舒服的。徒手 100 行 sql,返回结果可能就是 12 个月的平均销量,12 个数值而已。如果用 orm 那种方式,带宽、CPU 都跑满。哈哈哈。
    chnyuwen
        86
    chnyuwen   53 天前
    @JudyHal 这都能带上一个群体我是没想到的
    ArJun
        87
    ArJun   53 天前
    反驳一下楼主吧。技术不值钱,业务才是老板在乎的,换句话说有多少用户,对于中小公司只要不影响收钱上级一般不会太多干涉
    auh
        88
    auh   53 天前
    不想靠实力,当个混子又不犯法。
    xipushi
        89
    xipushi   53 天前
    做功能的时候,不可能把所有未来出现的情况都考虑到,当时能用就行了。有问题再慢慢优化。
    cxshun
        90
    cxshun   53 天前
    @sagaxu 这种大佬还留着吗?数据再多点,到了十万级别就够它喝一壶了
    Leviathann
        91
    Leviathann   53 天前   ❤️ 1
    @ipwx 我们现在也是,不过是写了个工具方法,底层就是分批后调用 jpa 的 find in,不是裸拼 sql 的话其实还挺方便的
    Eytoyes
        92
    Eytoyes   53 天前
    @xz410236056 #82 现在大佬们都讲究全栈(狗头
    wh469012917
        93
    wh469012917   53 天前
    @xz410236056 DBA 有说啊,说你们数据库负载大,他就以为是访问量大,得加配置
    Leviathann
        94
    Leviathann   53 天前
    看到 hibernate 的各种概念就头大,稍微复杂的查询我宁愿 jdbc 拼 sql
    CodeCodeStudy
        95
    CodeCodeStudy   53 天前
    @wh469012917 #77 我是说产生这种情况的原因,我并不认同整天吹分布式什么的
    gamexg
        96
    gamexg   53 天前
    看情况
    如果不存在性能问题,那么写的会很随意,怎么方便怎么来。
    聊起来,聊缓存等挺正常。

    但是如果真的碰到性能问题,
    对明显的 sql 语句问题不会优化,那就真的有问题了。
    wh469012917
        97
    wh469012917   53 天前
    @gamexg 很多接口因为 sql 查询太多,都超时了
    tairan2006
        98
    tairan2006   53 天前
    写 SQL 是基本功
    lithiumii
        99
    lithiumii   53 天前 via Android
    @play78 其实我是在讽刺另一种情况,会手写长 sql 瞎 join 的人太多,把生产数据库拖累了,我们踩过这个坑,后来就把给数据分析们的数据库分离了,爱咋写咋写去
    Actrace
        100
    Actrace   53 天前   ❤️ 1
    老老实实把基础 SQL 写好了就行了。
    存储过程,触发器,计划任务,都是坑。
    1  2  3  
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3602 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 09:48 · PVG 17:48 · LAX 02:48 · JFK 05:48
    ♥ Do have faith in what you're doing.