想在业务端维护 inner join 应该用什么算法?

2023-03-14 15:32:54 +08:00
 LeeReamond

数据库做连表压力有点大了,想要转到业务上维护,想问下版本答案用啥算法,没啥这方面的经验

场景是有 a 表数据和 b 表数据,两表用相同的主键索引,数据库方式的话应该是 a 做 b 的外键,但是现在没有这方面约束,a 和 b 的数据可能互相不一致,有的条目多一些有的条目少一些,想得到一个一致的结果,如果按直觉写多次遍历取交集这类的感觉复杂度有点高了。。。

2516 次点击
所在节点    程序员
40 条回复
ljrdxs
2023-03-14 21:17:34 +08:00
@shyangs 主要不是 programming language 的问题(看你用繁体字加台湾术语,我不熟悉台湾术语,所以全用 term )楼主应聘 Oracle 或 Microsoft ,应该没能力去 database team 开发 join 相关 implementation 。所以,他说 database join performance 差,要自己 implement ,感觉很奇怪啊。同样的 language ,同样的 version ,他的 materialization 能达到 Oracle 或 Microsoft 的水平?我看到不少人说 MySQL join 差,但是楼主应该没能力当 MySQL 的 contributor 。MySQL 团队,比楼主强多了吧?
所以,尽管楼主没回答我的细节提问。换我经历 performance issue ,第一件事,找 DBA 商量。
ljrdxs
2023-03-14 21:22:33 +08:00
@iseki 假如 MySQL 烂,也是比 Oracle 、SQL Server 烂。
和全世界绝大多数开发比,MySQL 团队肯定更强。
在这个论坛,自己实现同一个算法,性能超过 MySQL 的,能有几个?
所以,不理解楼主的情况。
iseki
2023-03-14 21:23:46 +08:00
@ljrdxs 我也只是斜眼一下~~
roundgis
2023-03-14 23:00:01 +08:00
@LeeReamond 有一種辦法是把這兩張表的字段合併為一張表 這樣就不需要 join 了

很多公司拿 db 當 nosql db 用就是差不多的路數

你可以找找相關的案例分享

現代數據庫的引擎優化得不錯 拿來當 kv store 用也沒有問題
roundgis
2023-03-14 23:02:13 +08:00
@ljrdxs mysql 8 join 性能大有改善 不過很多公司未必會升級
jones2000
2023-03-14 23:06:05 +08:00
加硬件, 内存,cpu 往上堆,就行了。今天下单, 明天升级机器, 速度立马就上来了。
LeeReamond
2023-03-14 23:57:16 +08:00
@gtx990 有千行级别的 join 需求,单行 join 我还问什么。。
nothingistrue
2023-03-15 09:53:15 +08:00
系统架构图先理一下。程序和数据库,即计算和存储合起来,才构成一个业务。你这和数据库分离的业务端是个什么鬼。如果你的业务端,指的就是可横向扩展多节点,并脱离数据库的程序,那就只是个单纯的计算节点,那就别说 inner join 了,它连任何跟数据存储有关的业务都做不了。

我们通常所说的能让程序干的活就不让数据库干,那基本针对的是单个实体(表上的一行记录),而不是针对整个存储(表)。可以针对一两个甚至上万个记录,让程序分批查询出来之后再内部做 join ,这本质上是计算而非存储。但要针对动辄百万记录的整个存储,让程序做 join ,那是不行的。后者要交给专门的存储处理去做,如果关系数据库不行,KV 数据库、内存数据库、Nosql 数据库,或者更好更贵的关系数据库能顶上去,普通程序肯定顶不上去。
realpg
2023-03-15 11:17:32 +08:00
@ljrdxs #22

可是数据库跑逻辑负载高,会降级整个系统的性能
如果单纯的把最小化数据取出来,分布式的计算节点去计算,就会降低数据库的 cpu 负载,只吃 io

这种优化是高并发互联网项目常做的,而商业软件就可以无脑都写存储过程里让数据库去飙 cpu
ljrdxs
2023-03-15 13:16:21 +08:00
@realpg 你是这个意思吧?
单个电脑,数据库性能>后端性能
但后端用了分布式,相当于 N 台电脑,所以 N 台电脑计算能力>数据库性能优势
这倒说得通。
realpg
2023-03-15 13:49:48 +08:00
@ljrdxs #30
不是这个意思,感觉你可能没怎么做过中型互联网项目
以 MYSQL 为例,其实维持主备也好,cluster 也好,维持他们的一致性其实开销是很大的,所以互联网项目这边,数据都都是优化成最简单可用查询,充分利用索引,转化为简单完全索引查询和简单 left join ,数据库的 cpu 能完全空闲是最好不过的了,只要 io 能跑就没啥性能瓶颈

而计算节点天生就是一堆的弹性扩容的,如果一个复杂的内联查询算法能够通过其他方法让数据库服务器返回给程序的记录数据容量( KB-MB 级)不会太离谱的大,分散到计算节点处理就完事了,对系统没有任何影响

RDB 这边,三机主备+1-8 只读节点就是最常见的中型以上( api server 10kQPS+)项目的最常见配置了

如果你把太多复杂的查询都压到了数据库上,让数据库 cpu 满载,查询造成积压,整个系统都不好了

压力压到数据库 cpu 上的复杂查询,大部分是乱 join 、group by having ,甚至直接内联 case when 之类,这些其实都不是好简单无代码直接优化到 kv 类的 nosql 上的,都需要算法协助才能充分利用 redis 之类的内存缓存

中型高 QPS 系统上,当数据库较弱时(比如 MySQL 弱鸡的索引和锁体系),基本 DBA 都会要求全简单查询化,全索引匹配化,甚至条件全 int 化把 varchar 都优化掉



与之相对的,就是写底负载商业软件的,前天帮人调试国产化数据库兼容,打开医院 HIS 系统,有个 TXT 资源文件,里面全是单行 SQL 代码都 1KB-2KB 的怪物查询。。。
nothingistrue
2023-03-15 14:02:22 +08:00
@ljrdxs #30
@realpg #31
ljrdxs
2023-03-15 14:03:18 +08:00
@realpg 做过大型,但不是后端。
转后端了,确实不做互联网。
大部分没看懂。不过用 Oracle ,刚好和你反过来,join 、group by having 、case when 才是性能最优。一个 SQL 解决问题,最好; select 越多,性能越差。我们有 profiling ,所以我敢说这些是对的。
不一定只和数据库类型有关,估计和你说的“都需要算法协助才能充分利用 redis 之类的内存缓存”有关。
realpg
2023-03-15 14:08:20 +08:00
@ljrdxs #33
你有试过 oracle 按你那种写法,把基本操作压 10kQPS 上去测过么
10kQPS 的业务 api 接口,算是互联网这边中型系统的门槛了
nothingistrue
2023-03-15 14:15:28 +08:00
@ljrdxs #30
@realpg #31
这个是把少部分数据,首先镜像到程序的数据结构(内存)上,然后在程序中再做后期处理。这样做的前提是,每次业务操作,只需加载少量的数据。当你在业务上(重点是业务,不是后台技术)周密的拆分数据结构之后(微服务、DDD 都是干这事的),CRUD 业务上除了查询外都能符合那个前提,查询则有点无解,要靠读写分离、独立查询器等方式来支持后才能搞。
raysonlu
2023-03-15 15:26:50 +08:00
看标题给我的疑惑是:算法?打算直接改数据库底层的相关源码进行维护?
Richard14
2023-03-15 16:13:38 +08:00
@nothingistrue 你说的缓算完全不是重点,重点在于原生 mysql 集群横向扩展困难,当压力上来了之后横向扩展导致的冷热备一致性 /热点 /IO 放大问题全都是老大难,而业务本身多变,有的业务读多,有的业务写多,有的热点集中,有的全局随机读写,各种歪瓜裂枣,极端情况也是屡见不鲜,你避不开这些问题。所以如果条件允许大家都要上虚拟储存层,关系型数据库本身就是为了维护复杂关系做的设计和优化,而按照我的经验来说业务往往对这些复杂关系的维护是非必须的,这样抛开关系型维护转化成单纯的索引后软硬件利用率都有质的提升,如果说一致性仍然是老大难,起码热点和 IO 放大问题会得到很好的缓解,并且抛开关系型数据库的抽象后可以更接近底层,对于充分利用硬盘本身性能的亲和也更好。楼主的方案是非常合理、且正常的。


@realpg 看得出来楼主很无语,全楼只有老哥一个正常参与讨论的,你回帖说的都是很常识性的东西,楼上有位这些常识都听不懂然后还回了好几条的,也不知道之前都在说些什么。这楼里都是一些什么妖魔鬼怪,v2 氛围什么时候变成这样了,首页都是在那无限外行的讨论 AI 取代人类的群魔乱舞,点开算法贴里没有一个人讨论算法,全在互相踩
realpg
2023-03-15 16:42:22 +08:00
@Richard14 #37

其实也不单纯的是 mysql 横向扩展困难 mysql 这么弱鸡的数据库去抗企业行业应用那种低 qps 负载,只要少用锁别干死锁了,都能扛得住,搞行业软件的跟搞对海量普通用户业务(我只是习惯叫互联网替代这种业务)的互相理解很难。

我们定义的大系统 crud api server 是 35kQPS(包含缓存操作),他们定义的大系统是 80 人开发 700 多个模块编译后二进制文件都 900MB 然后 15qps ,对数据库性能的理解我们是优化到单查询 0.0035 秒他们是 1 秒能出结果就行。


十五年前吧,我也搞过 oracle ,写企业商业软件简单到离谱,写医院的业务系统,20qps 都是高并发的超大大医院了
oracle 这玩意只要搭起来集群,给足了海量内存,四路服务器或者当年小型机堆上去,也不用怎么设计索引,看着差不多觉得可能用得到就上一个,剩下的 oracle 自己就能给你优化好,这就是搞商业软件行业软件的逻辑,跟面对庞大公众用户的基本思维就不同


比如,最近朋友公司在搞信创国产化,要绕过供应商把一个三甲特大型医院的一个大业务系统数据库从 oracle 替换成人大金仓,我听着直摇头,金仓就是魔改的 pg11 ,这怎么能行,一个特大型三甲那门诊量和住院医嘱量,oracle 的牛逼查询自适应优化能力,换弱鸡山寨 pg 怎么行,结果一换试了下,还真行。在中间件下了个性能检测记录 SQL 防止语法不兼容,结果 24 小时系统峰值读查询 qps45 ,医院上班工作时间平均读查询 qps15

---

关于讨论,V2 早就这样了,所以这些年我都不爱吱声了,顶天在 tg 群里遇到感兴趣的能说两句。

之前说的都是大家好理解的形象的常识,不说人话的不搭理就是了,更深入的不搞这个根本接触不到的你发了也没人看
要不就是真搞这个的还有问问问从来不自己研究,就差让你手把手教了

五六年前的 V2 讨论技术问题,还是可以只提供思路,现在,要么是一群啥也不懂的瞎参和,要不就是希望你手把手给他搭好才能证明你说得对的。。。
ruanimal
2023-03-15 18:17:43 +08:00
@shyangs Python PTSD ? 主贴根本没提到 Python 吧
nothingistrue
2023-03-16 09:21:57 +08:00
@Richard14 #37 你这不就是通用规则的数据库顶不住,就自己定制一个专用数据库吗。处理还都只是存储节点 /数据层,没到计算节点 /业务程序上。楼主说得业务端,虽然没给出架构图,但看描述八九不离十是个计算节点,不是一回事。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/923928

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX