硬核干货——《中小企业 AI 实战指南》免费下载! 了解详情
写点什么

在关系型数据库中运行计算

  • 2014-03-21
  • 本文字数:1577 字

    阅读完需:约 5 分钟

近日, JOOQ 的官方博客上发表了一篇文章,针对Stack Overflow 上“如何使用Hibernate 映射处理庞大的数据表”这样一个问题,作者认为有必要提醒下开发人员,不要犯 Java 开发人员编写 SQL 时常犯的十个错误中的第二项错误:在 Java 内存中处理数据。

Stack Overflow 上的问题可以归结为:从下面的中型表中计算出每个应用程序 ID 对应多少个状态为 0 或 1 的文档。用 Hibernate 该如何实现?

复制代码
AppID | DocID | DocStatus
------+-------+----------
1 | 100 | 0
1 | 101 | 1
2 | 200 | 0
2 | 300 | 1
... | ... | ...

“NO! 不要用 Hibernate!你要用 SQL。Es-Queue-EI!……”,作者认为,有许多简单的方法可以让 SQL 服务器来运行这种查询,而且时间很短,又不用在聚合之前将所有的数据加载到 Java 内存。他分别使用 GROUP BY、嵌套查询、SUM()和 PIVOT 给出了四种实现方式,并认为其中任何一种的性能都会在数量级上超过任何基于 Java 的实现。文章的结尾这样写道:

任何时候,只要合适就使用 SQL! 能用 SQL 的地方远比你想象的多。

该文在 reddit 用户之间引发了激烈的讨论。ggtsu_00 认为:

……如果计算减少了返回结果的行数,那么最好在数据库里计算。不过,许多计算是后处理或格式修改,这些最好是在应用服务器上进行。

对于 ggtsu_00 的观点,lukasedar 进行了补充,认为“争论的焦点是通过网络在处理数据的节点之间传输的数据量”。Grauenwolf 则表示,如果将该观点中的“返回结果的行数”改为“返回结果的行数或列数”,那么他也赞同。而该观点的后半部分则引发了进一步的争论。ItsMeCaptainMurphy 认为:

这要看你做什么,构建数据库通常是用来尝试并行的,对于行级操作尤其如此。……而且你的数据库服务器的性能可能比 Web 服务器或客户端更强大。那么,有些事情确实是最好在应用程序端做,但并不是所有情况,甚至不是多数情况。

不过,emn13 则认为这与数据库服务器的性能无关,而与代码性能相关:

本地或近似本地代码的性能通常是 SQL 的 1000 倍,而且可能更高。即使是像 Ruby 或 Python 这样相当慢的语言在简单表达式求值方面也可能比大部分 SQL 服务器要快。

SQL 不是一个很好的通用计算器。如果计算没能减少返回结果的行数,就不能想当然地认为一台高性能的数据库服务器实际上会超过一部手机。

……

总而言之,由于大部分计算都很简单,所以没有减少数据也没关系。但当计算代价很高时,SQL 通常是缓慢的。

为了使自己的观点更有说服力,他结合自身的经验作了进一步的说明:

1000 倍这个数量级是我在 MS SQL SERVER 上实现一个有向图节点计分算法时观察到的,不是假想的场景。

Ulukai 对上述观点表示了赞同,他还补充说

如果有非常复杂的逻辑需要执行,那么你应该仔细考虑。比如,我不会在数据库代码中执行“最短路径”算法,除非它获得原生支持。

在关系型数据库中进行计算,除了应用场景的问题,还有知识结构和使用习惯的问题。人们已经花了很多时间和精力来学习 ORM 框架的所有最细微的细节,所以他们真的不喜欢他们应该更好地学习 SQL 这样的建议。但 crimson_chin 认为:

学习任何一个而不学习另一个都会让你处于不利地位。如果学了 SQL 没有学 ORM,那你就要面临代码可能过于冗长且难以维护的风险。如果你学了 ORM 没有学 SQL,那么你就要面临自我折磨的风险,因为一个查询为了获取项的名称列表却拉回了 200 列。

但同时,他认为数据库代码难以测试、管理和维护。因此,只有在可以明确地知道是最佳实践的时候,他才会使用数据库的特性来进行开发。

总之,JOOQ 的博文虽然引发了一场讨论,但文章本身的内容似乎没有多大的争议。至于什么时候应该在关系型数据库中进行计算,什么时候应该在应用程序端进行计算,大家也有一定的共识。具体做法则要视应用场景,并根据 SQL、ORM 各自的优缺点进行综合分析和测试,而这当然离不开对 SQL 和 ORM 的学习和使用经验。

2014-03-21 20:212594
用户头像

发布了 256 篇内容, 共 98.0 次阅读, 收获喜欢 12 次。

关注

评论

发布
暂无评论
发现更多内容

架构师才需要学习的知识:亿级流量调优方法+实战

Java 性能优化 性能调优

详解,LED显示屏灰度等级

Dylan

灰度 LED显示屏 色彩

阿里P8:Java性能调优(独孤版),带你打造淘宝秒杀架构

Java 架构 性能调优

Seata:连接数据与应用

阿里巴巴云原生

阿里云 云原生 seata

OpenHarmony3.2release抢先体验

坚果

OpenHarmony 三周年连更

MySQL8.0 优化器介绍(二)

GreatSQL

MySQL greatsql greatsql社区

从此告别写SQL!DataLeap帮你零门槛完成“数据探查”

字节跳动数据平台

MySQL 数据分析 数据治理 数据探查 企业号 4 月 PK 榜

镭速Raysync v6.6.8.0版本发布

镭速

eBPF动手实践系列一:解构内核源码eBPF样例编译过程

阿里云大数据AI技术

运维 代码 企业号 4 月 PK 榜

对话大咖 | 人工智能+视频编解码能带来新的变革吗

小红书技术REDtech

人工智能 深度学习 活动回顾

原来XXL-JOB可以这么造

六月的雨在InfoQ

Serverless XXL-JOB SAE 三周年连更

阿里耗时1年:用283张图+24问完美诠释“Java并发编程”所有难点

Java 并发编程

Postman Runner 使用指南

Liam

Java 后端 Postman 接口测试 API 开发

从零开始学习 GraphQL:入门指南和教程

Apifox

程序员 gRPC 后端 协议 graphql

如何解决spring的循环依赖问题?

Java spring 循环依赖

如何将一个链表分组并对每组进行反转?

Java你猿哥

Java 链表 架构师 SSM框架 链表结构

高性能存储SIG月度动态:ANCK ublk完成POC测试,EROFS优化xattr元数据开销

OpenAnolis小助手

操作系统 内核 高性能存储 龙蜥社区 sig

数说热点|春暖花开日,露营正当时——当精致露营遇上新能源车

MobTech袤博科技

面试了个阿里P7大佬,他让我见识到什么才是“精通高并发与调优”

Java 高并发 性能调优

RocketMQ 多级存储设计与实现

阿里巴巴云原生

阿里云 RocketMQ 云原生

带你用三种不同的工具体验AI作诗

华为云开发者联盟

云计算 华为云 华为云开发者联盟 企业号 4 月 PK 榜

ChatGPT的狂欢背后:短板犹在,启发甚多,2023有这些事可以做……

小红书技术REDtech

人工智能 ChatGPT 活动回顾

记一次 MySQL 主从同步异常的排查记录,百转千回

Java MySQL 主从同步

Github上标星68.5K,阿里巴巴《MySQL成长手册》火了

Java MySQL 数据库

优秀的pdf编辑器:Acrobat Pro DC 中文直装版

真大的脸盆

Mac PDF Mac 软件 PDF格式转换

零拷贝浅析

数新网络官方账号

大数据 零拷贝

面试官:如何动态的给一个类增加功能?

SpringBoot设计了哪些可拓展的机制?

Spring Cloud微服务网关Zuul过滤链实现的源码解读

直播预告 | TDengine & Apache SeaTunnel 联合应用最佳实践

TDengine

Apache tdengine 时序数据库

人工智能会取代人类成为地球的主宰么?| 社区征文

毛小毛

人工智能 ChatGPT 三周年征文

在关系型数据库中运行计算_数据库_马德奎_InfoQ精选文章