写点什么

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

  • 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:212253
用户头像

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

关注

评论

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

“以终为始”的正确使用方式

石云升

思维模型 1月月更

异步调用如何使用是最好的方式?

CRMEB

亚信科技AntDB数据库荣获“2021金融科技应用创新突出贡献奖”

亚信AntDB数据库

AntDB 金融行业 亚信科技

前端工程师 2022 年必备的 7 个工具

开源之巅

JavaScript node.js

Linux之wc命令

入门小站

Linux

“在线设计”网络资源管理的源头活水

鲸品堂

通信运营商 在线设计平台

直播回顾:准确性提升到 5 秒级,ssar 独创的 load5s 指标有多硬核?| 龙蜥技术

OpenAnolis小助手

Linux 开源

微信的业务架构图和学生管理系统的毕业设计

Geek_8d5fe5

架构实战营

Flutter启动流程分析之插件化升级探索

得物技术

flutter Weex Google 框架 原生

恒源云(GPUSHARE)_AdderSR: Towards Energy Efficient Image Super-Resolution学习笔记

恒源云

人工智能 深度学习 计算机视觉

农业掀起“上链”潮 区块链等数字技术正成为乡村振兴新动力

CECBC

鉴释加入龙蜥社区,助力开源生态建设

OpenAnolis小助手

Linux 开源 社群 合作伙伴

☕【Java深层系列】「并发编程系列」让我们一起探索一下CompletionService的技术原理和使用指南

洛神灬殇

Java 线程池 CompletionService 异步执行 1月日更

第三方测评:GaussDB(for Redis)稳定性与扩容表现

华为云开发者联盟

redis 华为云 GaussDB(for Redis) NoSQL数据库 云原生NoSQL数据库

必读!如何有效的进行沟通

观测观测

鉴释加入龙蜥社区,助力开源生态建设

OpenAnolis小助手

Linux 开源

恒源云(GPUSHARE)_attention decoder效果不佳时如何应对

恒源云

深度学习 计算机视觉

基于Calcite的分布式多数据源查询

麒思妙想

MySQL 数据库 Apache Calcite gbase8a

2022年保障企业内网安全就用行云管家!免费试用!

行云管家

云计算 云平台 内网 云管平台

流批一体技术框架探索及在袋鼠云数栈中的实践

袋鼠云数栈

携程DBA负责人俞榕刚:OceanBase在携程的落地和实践

OceanBase 数据库

数据库 分布式 OceanBase 开源 携程 客户实践

从智能汽车到智慧出行,区块链能打通车联网的任督二脉吗?

CECBC

SparkSQL的入门实践教程

华为云开发者联盟

sql spark 编程 Sparksql 结构化数据

全栈工程师?你知道全流程工程师吗?

蜜糖的代码注释

Java 开发 后端技术

在线YAML转TOML工具

入门小站

工具

手把手教你丨小熊派移植华为 LiteOS-M

华为云开发者联盟

华为 鸿蒙 LiteOS 小熊派 移植

一款基于Java语言开发的,开源商业应用的模块化开发框架和智能管理平台-Axelor

马农驾驾驾

Java 系统开发 BPM 开发框架 智能管理

五步实现HarmonyOS应用(ets)【鸿蒙开发 07】

坚果

鸿蒙 1月月更

企业上云后,不容忽视的管理工具-云管平台

行云管家

云计算 企业上云 云管平台 云管理

用 docker 快速搭建 kafka(qbit)

qbit

kafka zookeeper docker image

高并发环境下,6个构建缓存服务需要注意的问题

华为云开发者联盟

缓存 高并发 开发 并发 缓存服务

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