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

互联网出身的不喜欢 db 层面的逻辑,纯当存数据。偏好 mysql;企业服务应用的喜欢在 db 层面搞,还有专门的存储过程开发。偏好 oracle,SQLserver。

  •  
  •   sandman511 · 2020-05-20 13:17:08 +08:00 · 5711 次点击
    这是一个创建于 1640 天前的主题,其中的信息可能已经有所发展或是发生改变。

    https://www.v2ex.com/t/673284 #12 @chenxytw
    看到隔壁帖子里有这个回复。
    工作第一年,我们公司的 SQL 都是几十甚至上百行的。用的 ORACLE 。完美符合标题后半句🐕
    请问正确且最合理的做法是什么,碰到各种多表联查,关联查询,不应该在 SQL 里完成吗,难道是在分批查出需要的数据,再用代码进行关联吗?

    51 条回复    2020-05-21 16:11:50 +08:00
    xuanbg
        1
    xuanbg  
       2020-05-20 13:25:13 +08:00   ❤️ 4
    多表联查是基操,这个和是不是互联网没关系。但有些沙雕确实不懂 SQL,所以就很排斥 SQL 。同时为了掩盖自己无能的事实,就鼓吹单表,鼓吹 NoSQL 。
    lolizeppelin
        2
    lolizeppelin  
       2020-05-20 13:30:00 +08:00
    因为 mysql 干这事会死....
    yafoo
        3
    yafoo  
       2020-05-20 13:33:33 +08:00 via Android
    可能跟性能有关系,sql 里写逻辑,遇到性能问题,不好优化。如果程序处理逻辑的话,可以随意优化。另外就是模块化,后期维护,上百行的 sql 语句,后期没法维护。
    MeteorCat
        4
    MeteorCat  
       2020-05-20 13:35:45 +08:00 via Android   ❤️ 2
    主要是场景不同,传统企业并不在意速度,但是对数据特别敏感,特别在财务类应用中宁愿你卡也不需要重构优化,实际 oracle 更加像是数据仓库
    lhx2008
        5
    lhx2008  
       2020-05-20 13:36:06 +08:00 via Android
    储存过程肯定是要有一大段的时候才用,互联网业务执行一大段 sql 还不是很常见吧
    zoharSoul
        6
    zoharSoul  
       2020-05-20 13:37:37 +08:00
    因为 mysql 干特别复杂的查询会挂掉... 要有这么强谁还用 oracle...
    xmh51
        7
    xmh51  
       2020-05-20 13:40:16 +08:00
    以我的浅薄经验看,和性能要求有关。性能要求高的话,负载全在数据库,很容易出问题。企业服务的特点是查询类需求复杂,性能要求低,这个有点类似 BI 。事实上互联网公司的 bi 也是大量用类 sql 出报表的
    constantine008
        8
    constantine008  
       2020-05-20 13:40:45 +08:00
    之前呆的一家公司用的 mysql,在稍微有一点点并发量的情况下就出现大量慢查询把数据库服务器 CPU 直接占满,看了下代码,都是多表联查导致的,所以我觉得写 SQL 语句时只考虑业务,不注重优化的话,很容易出现性能问题。但有时一些业务场景要做到两者兼顾有点难,只能取舍。以上仅代表我个人的经验
    tctc4869
        9
    tctc4869  
       2020-05-20 13:42:06 +08:00
    mysql 真的很弱么?和 postgresql 相比呢?
    luin
        10
    luin  
       2020-05-20 13:43:14 +08:00
    关联查询互联网公司肯定也会用的(如果用的是关系型数据库),只是物理外键很少用。主要还是有状态的服务毕竟难 scale out,无状态的服务就容易很多。互联网公司高负载的场景会多一些(其实我觉得大部分初创互联网公司的负载也没高到需要考虑这个的地步),所以会尽量把任务放到无状态的服务上。另外扩展需要的情况下采用数据库异构方案后,都是 ACID -> BASE,所以也不太依靠特定的数据库功能来实现一致性之类的,还是要靠应用端来解决
    swulling
        11
    swulling  
       2020-05-20 13:45:23 +08:00   ❤️ 13
    从 12306 的演化过程就知道企业开发和互联网的区别了。

    12306 最早的版本性能比较差,但是非常的准确,说有几张票就有几张票,数据强一致,在不崩溃的时候用户体验很好。崩溃页面能看到一个比较复杂的 SQL 查询,可以认为就是按照原来的企业开发的模式开发的。

    现在版本的 12306,说有票但是下单就没票,有时票都卖光了,页面上还是显示有票。放弃了数据强一致性完全为了保证系统不崩溃,所有的抢票请求全部扔到队列里后台慢慢消费,前面看到的全都是 cache,自然没必须使用什么复杂的查询逻辑。
    xiangyuecn
        12
    xiangyuecn  
       2020-05-20 13:46:27 +08:00
    好奇数据库里面存的 sql 存储过程之类的,成白上千行怎么进行版本管理之类的,方便 review 变更?还是说另外存一份 sql 文本文件,每次改这个文件,然后扔数据库执行一遍生效?😳
    wangyzj
        13
    wangyzj  
       2020-05-20 13:46:51 +08:00
    这不是偏好把
    这是实际业务场景决定的
    saberlong
        14
    saberlong  
       2020-05-20 13:48:40 +08:00 via Android
    互联网企业对查询有要求。一个复杂的 SQL,一次查询占用大量 CPU 和 IO,即使查询速度足够,也会导致并发上不去。另外数据不均衡,有些大表需要分库分表时,连 JOIN 都没法自由使用。
    xuanbg
        15
    xuanbg  
       2020-05-20 13:48:49 +08:00
    不过话说回来,存储过程、触发器什么的还真的不推荐,最多搞搞自定义函数和视图。
    MeteorCat
        16
    MeteorCat  
       2020-05-20 13:49:06 +08:00 via Android
    @tctc4869 这两者都不弱,但是吃配置优化和性能调优,我记得 mysql 之类最底层要重新编译替换内存申请库从而达到最高效率,这些资料很稀少且基本上没有什么直观感受,用付费服务 oracle 就不用关心这种
    jtwor
        17
    jtwor  
       2020-05-20 13:51:16 +08:00
    用存储过程感觉还是必要 能隔绝脏数据
    saberlong
        18
    saberlong  
       2020-05-20 14:00:11 +08:00 via Android
    说白了就是尽可能提高资源利用率。性能要求已经超出一台机器所能承载的时候,不可能所有服务器围观一台数据库服务器干活。要么服务端处理这块逻辑,要么使用分布式数据库。
    encro
        19
    encro  
       2020-05-20 14:00:22 +08:00   ❤️ 2
    1,因为以前那些厂商都需要定制,每个公司的 SQL 和程序版本都可能不一样,改数据库比改程序方便多了,不用发包;
    2,因为企业应用很多是按时间收费和按需求点收费,完成一个需求,最快的办法就是写存储过程啦,不需要改界面和接口,发包;
    3,传统应用一个公司一个数据库,性能不够,硬件来堆;互联网企业所有客户可能公用一个数据库,响应时间超过 1 秒用户就要骂,所以对性能要求更高,所以需要足够简单和高效的数据库。
    4,mysql 和 pg 也支持复杂查询,用的人少,是因为逻辑放在程序里面比较好维护,如果程序里面也有,存储过程也有,最终不知道去那里找。传统公司人员流动少,所以他们可以放存储过程里面,难理解也没关系。
    5,传统公司用 oracle 和 sql server 有一个好处是每年收费,数据库公司对外报价 10 万一年,收客户 10 万,实际软件开发公司可能 2 万,这一年 8 万的差价赚得多开心?
    6,传统 erp,oa 很多涉及如权限、递归等,确实查询复杂,使用程序实现,不如采用数据库物化视图,存储过程之类实现,程序不用修改或者少量修改,只要修改数据库就能得到性能提升。


    至于说 mysql 复杂查询会挂掉的,大概分不清锁表和锁行,理不清楚查询复杂度概念,选择性无视 mysql,pg 的企业列表,也重来没看见过“阿里放弃 Oracle 选 MySQL”之类的文章。
    zpf124
        20
    zpf124  
       2020-05-20 14:01:53 +08:00
    这是我很久之前在另一个外键相关问题里的想法,(说外键影响性能) https://v2ex.com/t/626162

    zpf124 166 天前

    对于外键影响性能这点我一直持保留态度,如今的传统互联网项目的结构性数据都不一定有 20 年前的银行这类传统大型企业数据量大。
    而当年那些企业哪个不用外键? 如果性能影响真的大,当年计算性能比现在低那么多肯定早就有公司和产品将不用外键推广出来了。


    外键对于如今而言最大的缺点其实是灵活性,曾经许多方法和算法为了高性能都用存储过程写到了数据库里,而这些年在互联网企业的示范下我们将这些都挪到了后端代码里,并且从前几年就开始流行将代码再向前挪——GraphQL,因为性能其实没那么吃紧了, 大不了找方法做横向扩展加机器嘛。

    而这个时候对于业务层而言,后面那些层就仅仅是提供数据的,只要准确快速即可,业务层自己是就是全功能的,自己来给用户做约束,而不希望后面那些层再额外限制约束业务层影响业务层的功能。
    在这种思考方式下,如果他是后端代码实现逻辑的,那么它就不希望数据库来存在存储过程,外键,等在后端代码控制范围外的约束来干扰它。
    如果是 GraphQL 的那则是希望连后端代码都别做太多约束限制影响它的查询。
    love
        21
    love  
       2020-05-20 14:04:59 +08:00 via Android
    在数据库里面大量写代码不管是调试还是测试都不如在外面写吧?
    dcoder
        22
    dcoder  
       2020-05-20 14:08:03 +08:00
    1. 几百行的 SQL, 各种外键连查.
    2. GraphQL, 让前端把后端当 SQL 用.

    1, 2 都是错误的路子. 1 应该入土埋了. 2 应该拿去枪毙. XD
    ayavvv
        23
    ayavvv  
       2020-05-20 14:09:53 +08:00
    @xuanbg 喷子真尼玛无脑,写复杂 sql 就有能?互联网公司离线数据库动不动几亿几十亿数据量有让你写复杂 sql 分析查询的地方。实时业务写复杂 sql 才无能。业务不放在代码里面放在 sql 里面才无能。
    liprais
        24
    liprais  
       2020-05-20 14:11:03 +08:00
    毕竟互联网界会写 sql 的不多
    pmispig
        25
    pmispig  
       2020-05-20 14:11:37 +08:00
    因为 mysql 对这方面比较弱,另外你说的几百行 sql 其实不太适合高并发。我看本质问题是应该把计算放到应用层,便于扩展。你把大多数业务计算放在 mysql,扩展难度大,也不划算
    zpf124
        26
    zpf124  
       2020-05-20 14:18:05 +08:00
    如今我还是这个意思, 互联网应用会收到远超过去的传统行业的项目的并发轰炸。
    但数据本身的复杂性和量级则大多不如过去传统企业项目。

    因为过去数据结构复杂但机器性能有限,所以出现了数据库三范式,以及使用索引,外键,存储过程各种可以优化查询与执行的方法。

    如今对于互联网企业 并发巨大,但机器其实廉价且性能比较富裕,毕竟并发可以通过横向扩展多机分担,而不像当年程序本身在这机器上满载执行就那么慢你能有什么办法。

    所以在互联网企业时代,什么狗屁数据库三范式,我数据冗余存多份,每个关联数据里不止存操作人 id,连他的用户名和头像一起存下来,查的时候单查一个表,不比你多表查询快么。再不够就加缓存,当前显示准不准又有什么重要的。
    encro
        27
    encro  
       2020-05-20 14:22:29 +08:00
    @zpf124

    外键影响性能?

    如同一群人讨论雨滴从高空落下来会不会砸死人。

    当数据库开发人员是沙雕?

    自己一试不就知道了?

    正确的外键不但不会降低性能,可能还会优化性能(比如:1,外键一般都建立了索引; 2,对于大部分数据库来说,如果你用外键,不能存储 0 值,但是可以存储 null 值,而数据库应该都对 null 值索引有优化)。如果说影响性能,唯一可以说的是索引需要花时间建立和占内存,以及修改当前数据的时候。

    外键,本质只是一个检查规则,其实就是一条潜在的触发器,这条规则只影响当前这条数据增删改查的时候。

    所以,我认为说外键影响性能,绝大多数情况是因为 sql 没写好,用关联查询没有注意查询复杂度,导致的性能底下,然后被外键背了锅。

    说外键影响性能的人缺乏思考和分析。
    james122333
        28
    james122333  
       2020-05-20 14:29:53 +08:00
    开始战了 (滑稽)
    不过本人确实不太喜欢 SQL 个人听大佬的话就对了
    encro
        29
    encro  
       2020-05-20 14:31:15 +08:00
    @zpf124
    但数据本身的复杂性和量级则大多不如过去传统企业项目。

    数据没有复杂性,使用方式才复杂:
    用户,权限,角色,工作流等这些在数据库都非常简单,是查询复杂。互联网项目会采用用户登录时候缓存,使用时检查策略;传统项目采用物理表,物理视图,关联表,或者让它慢的策略。

    互联网项目多个公司公用一个数据库,远非传统项目能比:
    互联网项目一个小公司数据库藏着几千万条数据,传统项目 1000 人公司运行了几年可能还是不到一千万记录。
    janxin
        30
    janxin  
       2020-05-20 14:48:57 +08:00   ❤️ 1
    取舍自然是有前提条件的,抛开业务应用场景谈取舍都是耍流氓...
    yaphets666
        31
    yaphets666  
       2020-05-20 14:59:06 +08:00
    按我的菜鸟理解 互联网企业需要高并发 高性能 存储过程是不被允许存在的
    zichen
        32
    zichen  
       2020-05-20 15:02:39 +08:00
    前东家都是几百行的存储过程,都是陈年老代码没人改动,有一次我改了一个业务,线上出错了,调试起来那叫一个费劲。
    gemini767
        33
    gemini767  
       2020-05-20 16:20:57 +08:00
    olap 和 oltp 区分开就好了
    还有就是没有最正确的做法,技术是解决现实问题的,满足当前需求,且满足可遇见的增长需求,就是正确的做法,technical debt 才是推动技术进步的动力
    back0893
        34
    back0893  
       2020-05-20 16:40:23 +08:00
    业务经常变..用外键想死..
    akira
        35
    akira  
       2020-05-20 17:01:18 +08:00
    任何时候,把一个复杂的事情,拆分成多个简单的小任务,都是合情合理的吧。。。。
    troywinter
        36
    troywinter  
       2020-05-20 19:02:28 +08:00
    复杂 sql 大家看看文档都会写,问题是两个业务场景是不一样的,互联网公司的业务场景通常用户数较多,并发会比较大,企业应用的场景大部分可能只是一个公司内部的用户比较多,并发也较少,联表查询是可以接受的,在高并发场景下把大的数据库请求拆分成小的,是比较正常的做法,其次就是写在代码里比较容易改变,并且提供了较好的扩展性。
    levelworm
        37
    levelworm  
       2020-05-20 19:16:32 +08:00 via Android
    几十一百行的不稀奇,一般都是上千的存储过程。。。
    thtznet
        38
    thtznet  
       2020-05-20 19:45:42 +08:00
    怎么说呢,这个要看业务的场景去判断,没有标准答案。不管互联网还是传统企业服务,制约技术架构的只有 2 个因素:需求和资源。前者是你的(客户的)最终目的是干什么,后者是你(客户)打算投入多少资源(人和钱)来达到目的。互联网抛去 db 的做法是由于互联网的数据存量大,对事务一致性的要求低,大多采用的是最终一致性,而海量数据的结果必然抛弃以 db 为中心设计,采用以领域驱动设计,只要云服务资源足够,db 的所有数据在适当的时候都会被代码拉到内存里,然后以模型为最小单位进行操作、并联、查询等。传统企业服务也可以使用互联网的设计思路,但有一个很重要的制约因素是投入的资源不足,也就是没钱没人,没钱没人意味着传统企业服务技术团队没有资源和时间去参考互联网的架构(比如微服务)来完成整套业务系统的设计和实现,例如光一个分布式事务就够吃一壶了,所以在资源不够的情况下选择使用大厂高度完成的成品件来实现业务,选 mssql,在一个"BEGIN TRAN"里塞一堆 Update 就能简单地完成跨模型的数据一致性更新,半天就把活整齐全了,更别说配上 ORM 了。同样需求换成微服务架构,跨微服务更新模型你需要搞定领域服务,各种 Mapper,服务间调用,缓存、最终一致性设计,事件溯源,内存要大,数据库里所有数据都要读到模型里,Model 中间各种连接,识别聚合根还是实体,实体引用还是 Id 引用,各种麻烦的思考,不是不能实现,而是有没有足够的人力和资源来投入去实现的问题。
    namelosw
        39
    namelosw  
       2020-05-20 20:56:47 +08:00
    不是迫不得已不要依赖 SQL,抽象隔离。不然换不掉。
    tyrantZhao
        40
    tyrantZhao  
       2020-05-20 21:06:13 +08:00
    高性能 mysql 里不是狠推荐在 sql 层做太多逻辑
    liprais
        41
    liprais  
       2020-05-20 21:26:08 +08:00 via iPhone
    @thtznet 你说的互联网这一套,能做的正确真是奇迹。
    we6100
        42
    we6100  
       2020-05-20 22:57:11 +08:00 via iPhone
    MySQL 要短平快,复杂的 sql 还是交给 Oracle 吧
    neoblackcap
        43
    neoblackcap  
       2020-05-21 03:43:12 +08:00
    @dcoder GraphQL 是好东西,不过这个东西要配合好,相当于再造 SQL 解析层
    lolizeppelin
        44
    lolizeppelin  
       2020-05-21 09:49:37 +08:00
    不要把 pg 和 mysql 放一起啊, pg 可以对标商业数据库,mysql 可不行

    mysql 就是不能做复杂查询,数据量一大就玩完。

    mysql 没有足够的统计数据根本不能做查询优化路径选择

    不要迷信什么大厂也用 mysql 做复杂查询,人家应用层和数据库层都可以定向设计,可以玩出花来,我们可不行

    普通用户老老实实用 PG 做这些
    dk7952638
        45
    dk7952638  
       2020-05-21 09:55:10 +08:00
    @zoharSoul Oracle 也不是用来“用 SQL 干特别复杂的事”的数据库,SQL 写的特别复杂不是炫技就是蠢
    newmlp
        46
    newmlp  
       2020-05-21 09:58:06 +08:00
    个人不太喜欢把逻辑放到数据库处理,我觉得数据库就是存数据的,而且很多时候数据库就一个,应用服务有很多,还是把逻辑放在应用里分散下压力比较好
    buzailianxi
        47
    buzailianxi  
       2020-05-21 09:59:55 +08:00
    鼓吹 重度数据库的 没自己维护国别人的 SQL 吧,那真是想死,真想把之前的人揪过来 干死他
    dorothyREN
        48
    dorothyREN  
       2020-05-21 10:07:51 +08:00
    @encro #27 外键影响的是插入性能。
    xuanbg
        49
    xuanbg  
       2020-05-21 11:57:10 +08:00
    @buzailianxi 鼓吹重度数据库的我是真的没见过,鼓吹单表的倒是有不少。数据库只是一个存数据的工具而已,正确使用就行。要会正确使用数据库,你必须先懂一些基本的数据库知识,能够编写中等复杂度的 SQL 语句,知道怎么看查询计划,知道基本的优化方法。然后,根据你的业务特点,该怎么做怎么做,哪怕大量使用存储过程,或者完全抛弃关系型数据库也是正常的。

    但是有些人不,不管你的业务是什么,上来就先喷一下传统的关系型数据库,鼓吹一番 NoSQL 是多么潮流,仿佛你不抛弃 SQL 就是 lowB 。即使你要用 MySQL,也只能用单表,而且信誓旦旦单表几亿数据你没法用 join 。咳咳,单表几亿数据确实没法再联表查询了,那个速度真真是感人。但是,哪个懂点数据库的会让单表数据上亿啊!分表不会分吗?如果非得要用单表存几亿条数据,MongoDB 他不香吗?如果还要全文检索,ES 他是不擅长还是咋的?

    所以鼓吹单表的,有一个算一个,都是根本不懂数据库的 lowB 。
    index90
        50
    index90  
       2020-05-21 14:14:28 +08:00
    你作为一个小研发,当然不关心 Oracle SQLServer 要花多少钱啦。
    别看现在互联网好多钱,以前都是一个个屌丝来的啊,哪里花得起钱上 IOE 啊。

    还有,写个 SQL 怎么就写出优越感了,用单表查询都是因为不懂 SQL 吗?

    试试考虑给 blog 开发一个接口,根据文章 id,查询文章内容及评论。
    初级后端开发:根据 id 查询文章内容,根据 id 查询评论
    传统后端开发:根据 id 组成 join 查询语句,把查询丢给 db 处理
    现代后端开发:根据 id 同时查询文章内容和评论,组合并返回
    chmaple
        51
    chmaple  
       2020-05-21 16:11:50 +08:00
    技术选型不是自己做的,是所在团队决定的,所以到底哪种好我也不想发表意见。
    我用的是 MySQL+MyBatis 。
    1 、多表连接查询是日常操作;
    2 、单表数据量不会超过千万级别,有超过可能或者需求就分表;
    3 、个人更喜欢用 Stream 去处理集合问题,比复杂的 SQL 更简洁和易懂,更容易调试中间数据变动;
    4 、数据库有连接池,多查几次耗不了多少性能,但是也不会无脑 foreach 中去 selectById ;
    5 、压力放 CPU 和内存多好,反正计算又不需要 IO 操作,不废性能,数据库搞多了锁行锁表影响并发性能;
    6 、业务锁用的是自己改造过的 Redis 锁,不去做数据库的表锁。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1120 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 23:22 · PVG 07:22 · LAX 15:22 · JFK 18:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.