在sql和应用程序中执行计算的优缺点是什么

hel*_*ava 146 .net java sql postgresql performance

shopkeeper 表有以下字段:

id (bigint),amount (numeric(19,2)),createddate (timestamp)
Run Code Online (Sandbox Code Playgroud)

比方说,我有上表.我想获取昨天的记录并通过将金额打印到美分来生成报告.

一种方法是在我的java应用程序中执行计算并执行简单查询

Date previousDate ;// $1 calculate in application

Date todayDate;// $2 calculate in application

select amount where createddate between $1 and $2 
Run Code Online (Sandbox Code Playgroud)

然后遍历记录并在我的java应用程序中将金额转换为美分并生成报告

另一种方法是在sql查询本身中执行计算:

select cast(amount * 100 as int) as "Cents"
from shopkeeper  where createddate  between date_trunc('day', now()) - interval '1 day'  and  date_trunc('day', now())
Run Code Online (Sandbox Code Playgroud)

然后遍历记录并生成报告

在某种程度上,我的所有处理都是在java应用程序中完成的,并触发了一个简单的查询.在其他情况下,所有转换和计算都在Sql查询中完成.

上面的用例只是一个例子,在实际情况中,表可以有许多列需要处理类似的类.

你能告诉我哪种方法在性能和其他方面更好,为什么?

Mar*_*ell 199

这取决于很多因素 - 但最重要的是:

  • 计算的复杂性(喜欢的应用程序的服务器上做复杂的捣鼓,因为它可以扩展出来,而不是一个数据库服务器,它扩展)
  • 数据量(如果您需要访问/聚合大量数据,在数据库服务器上执行此操作将节省带宽,如果可以在索引内部完成聚合,则可以使用磁盘io)
  • 方便(sql不是复杂工作的最佳语言 - 特别是对于程序工作来说不是很好,但对于基于集合的工作非常有用;但是糟糕的错误处理)

与往常一样,如果您确实将数据带回应用服务器,那么最小化列和行对您有利.确保查询被调整并适当地编入索引将有助于任一场景.

请注意:

然后遍历记录

循环遍历记录几乎总是在sql中做错事 - 编写基于集合的操作是首选.

作为一般规则,我更喜欢将数据库的工作保持在最低限度"存储此数据,获取此数据" - 但是,总有一些情况下,服务器上的优雅查询可以节省大量带宽.

还要考虑:如果这在计算上很昂贵,可以在某处缓存吗?

如果你想要一个准确的 "哪个更好"; 对它进行编码并对其进行比较(注意,任何一个的初稿都可能没有100%调整).但考虑到典型用法:实际上,如果它被一次调用5次(单独),那么模拟:不要只比较一个"其中1个与其中1个".

  • +1"for循环几乎总是sql*中的错误" (60认同)

Erw*_*ter 83

让我用一个比喻:如果你想在巴黎买一条金项链,金匠可以坐在开普敦或巴黎,这是一个技巧和品味的问题.但是你永远不会把大量的金矿石从南非运到法国.矿石在采矿现场(或至少在一般区域)加工,只有黄金被运输.应用程序和数据库也应如此.

PostgreSQL而言,你可以非常高效地在服务器上做任何事情.RDBMS擅长复杂查询.对于程序需求,您可以从各种服务器端脚本语言中进行选择:tcl,python,perl等等.不过,我大多使用PL/pgSQL.

最糟糕的情况是重复进入服务器以获取更大集合的每一行.(这就像运输一吨矿石一样.)

排在第二位,如果您发送一系列查询,每个查询都取决于之前的查询,而所有查询都可以在服务器上的一个查询或过程中完成.(这就像运送黄金,并且每个珠宝都有一个单独的船,顺序.)

在应用程序和服务器之间来回走动是很昂贵的.对于服务器客户端.试着减少它,你将赢得 - ergo:在必要时使用服务器端程序和/或复杂的SQL.

我们刚刚完成了一个项目,我们将几乎所有复杂的查询打包到Postgres函数中.该应用程序移交参数并获取所需的数据集.快速,干净,简单(对于应用程序开发人员),I/O减少到最低......闪亮的项链具有低碳足迹.

  • 我会谨慎地使用这个类比来与其他开发人员进行有意义的设计决策.类比更像是一种修辞手段,而不是一种逻辑手段.除了其他因素之外,将数据发送到应用服务器比将金矿石运送到金匠要便宜得多. (12认同)
  • +1 - 一个易于理解的类比的优秀答案 (10认同)
  • 我真的很喜欢你的比喻,从现在开始它将完全被窃取:) (3认同)
  • 如果您没有将矿石转化为黄金的技术,或者贵的(因为矿工想要杀死其他工人),您将根据更便宜的价格发送矿石或黄金,您将把它运到另一个地方,也许在金匠和矿工之间,特别是如果你有一个以上的金匠. (3认同)

Jam*_*son 17

在这种情况下,您在SQL中进行计算可能稍微好一些,因为数据库引擎可能具有比Java更高效的十进制算术例程.

通常,对于行级计算,没有太大区别.

它确实有所作为:

  • 数据库引擎中的SUM(),AVG(),MIN(),MAX()等聚合计算将比Java实现快一个数量级.
  • 计算用于过滤行的任何位置.在DB上过滤比读取行然后丢弃它更有效.


Luk*_*der 12

关于在SQL中应该执行哪些数据访问逻辑部分以及应在应用程序中执行哪些部分,没有黑/白.我喜欢Mark Gravell的措辞,区分

  • 复杂的计算
  • 数据密集型计算

SQL的力量和表现力被严重低估了.自从引入窗口函数以来,可以在数据库中非常容易和优雅地执行许多非严格的面向集合的计算.

无论整体应用程序架构如何,都应始终遵循三条经验法则:

  • 保持数据库和应用程序之间传输的数据量变薄(有利于计算数据库中的内容)
  • 保持数据库从磁盘加载的数据量变薄(有利于让数据库优化语句以避免不必要的数据访问)
  • 不要通过复杂的并发计算将​​数据库推送到CPU限制(有利于将数据拉入应用程序内存并在那里执行计算)

根据我的经验,有了一个像样的DBA和一些关于你的体面数据库的体面知识,你不会很快遇到你的DBs CPU限制.

进一步阅读这些内容的解释: