写点什么

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

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

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

关注

评论

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

云边协同类型

lenka

3月日更

翻译:《实用的Python编程》05_00_Overview

codists

【技术干货】如何评价一款App的稳定性和质量?

性能优化 App 应用崩溃 anr 友盟

喜讯 | 音视频云服务商拍乐云荣登「2021值得关注的中国教育公司」榜单

拍乐云Pano

音视频 在线教育 互动课堂 白板 教育科技

分销的智能变局,华为好望云服务的铁索连环

脑极体

翻译:《实用的Python编程》05_01_Dicts_revisited

codists

Python

二分查找以及变体

一个大红包

3月日更

这是看脸的时代吗——晕轮效应

Justin

心理学 28天写作 游戏设计

手机高端化,需要不同却被认同

脑极体

Wireshark 数据包分析学习笔记 Day8

穿过生命散发芬芳

Wireshark 数据包分析 3月日更

Python With 关键字和语句

HoneyMoose

3月12日学习笔记

Nydia

(28DW-S8-Day20) 以太坊账户

mtfelix

28天写作

DCache 分布式存储系统|List 缓存模块的创建与使用

TARS基金会

MySQL nosql 微服务 分布式缓存 TARS

【数独问题】入门题:判断一个数独是否有效 ...

宫水三叶的刷题日记

面试 LeetCode 数据结构与算法

微服务简介

insight

微服务 3月日更

多元化:为什么会产生不良资产?

boshi

战略思考 七日更 创业失败启示录

算法攻关 - 验证二叉搜索树 (O(n))_098

小诚信驿站

刘晓成 小诚信驿站 28天写作 算法攻关 验证二叉搜索树

62图带你入门Docker

我是程序员小贱

容器 面试 3月日更

微软的各种考试,不知道是不是真的“香”

IT蜗壳-Tango

3月日更

算法喜刷刷之验证二叉树的前序序列化

Kylin

算法 3月日更 刷题笔记

滚雪球学 Python 之闭包操作,本系列第 8 篇文章

梦想橡皮擦

28天写作 3月日更

“种”下黑科技,守护每株绿,“植”了!

华为云开发者联盟

华为 AI IoT modelarts 森林

网页设计指南

张鹤羽

28天写作 3月日更

高效处理日均超 1000 亿次广告请求!Mobvista 是如何做到的?

亚马逊云科技 (Amazon Web Services)

《精通比特币》学习笔记(第八章)

棉花糖

区块链 学习 3月日更

互联网人一天24小时在做些啥《打工人的那些事》

谙忆

CloudQuery, 一款基于WEB的数据库客户端(转自杨建荣的工作笔记)

BinTools图尔兹

最简单的JVM内存结构图

叫练

JVM 堆栈 Java虚拟机 堆栈溢出 内存优化

10 个解放双手超实用在线工具,有些代码真的不用手写

比伯

Java 编程 架构 计算机 技术宅

公平

ES_her0

28天写作 3月日更

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