Java 与在应用程序中执行计算相比,在sql中执行计算的优缺点是什么
Java 与在应用程序中执行计算相比,在sql中执行计算的优缺点是什么,java,.net,sql,performance,postgresql,Java,.net,Sql,Performance,Postgresql,shopper表中有以下字段: id (bigint),amount (numeric(19,2)),createddate (timestamp) 比方说,我有上表。我想要昨天和明天的唱片 通过将金额打印为美分生成报告 一种方法是在我的java应用程序中执行计算并执行一个简单的查询 Date previousDate ;// $1 calculate in application Date todayDate;// $2 calculate in application select a
shopper
表中有以下字段:
id (bigint),amount (numeric(19,2)),createddate (timestamp)
比方说,我有上表。我想要昨天和明天的唱片
通过将金额打印为美分生成报告
一种方法是在我的java应用程序中执行计算并执行一个简单的查询
Date previousDate ;// $1 calculate in application
Date todayDate;// $2 calculate in application
select amount where createddate between $1 and $2
然后在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())
然后循环浏览记录并生成报告
在一种方式中,我的所有处理都在java应用程序中完成,并触发一个简单的查询。
在另一种情况下,所有转换和计算都在Sql查询中完成
上面的用例只是一个示例,在实际场景中,一个表可以有许多列,这些列需要类似的处理
您能告诉我哪种方法在性能和其他方面更好吗?为什么?这取决于很多因素,但最关键的是:
- 计算的复杂性(更喜欢在应用程序服务器上进行复杂的运算,因为这会向外扩展;而不是在db服务器上进行扩展)
- 数据量(如果您需要访问/聚合大量数据,在db服务器上执行此操作将节省带宽,如果聚合可以在索引内完成,则可以节省磁盘io)
- 便利性(对于复杂的工作,sql不是最好的语言——特别是对于过程性工作,sql不是最好的语言,但是对于基于集合的工作,sql非常好;但是错误处理很糟糕)
如果你想要一个准确的“哪个更好”;用两种方式编写代码并进行比较(注意两种方法的初稿都可能没有100%调优)。但将典型用法考虑在内:如果在现实中,它一次被调用5次(分别),那么模拟一下:不要只比较一个“1对1”。一般来说,如果同一个或其他项目中的其他模块或组件也有可能需要获得这些结果,那么就在SQL中执行操作。在服务器端完成的原子操作也更好,因为您只需要从任何db管理工具调用存储的过程即可获得最终值,而无需进一步处理 在某些情况下,这并不适用,但当它适用时,它是有意义的。一般来说,db box具有最好的硬件和性能。在这种情况下,使用SQL进行计算可能会稍微好一些,因为数据库引擎可能比Java具有更高效的十进制算术例程 一般来说,虽然行级计算没有太大差异 它真正起作用的是:
- 聚合计算,如SUM()、AVG()、MIN()、MAX(),在这里,数据库引擎将比Java实现快一个数量级
- 计算用于筛选行的任何位置。在数据库中进行过滤比读取一行然后丢弃它要有效得多
在决定将代码放置在何处之前,您还可以考虑许多其他方面。有一种看法是完全错误的——一切都可以用Java(应用程序代码)和/或db(sql代码)做得最好。让我用一个比喻:如果你想在巴黎买一条金项链,金匠可以坐在开普敦或巴黎,这是技能和品味的问题。但你永远不会为了这个目的把成吨的金矿从南非运到法国。矿石在采矿现场(或至少在一般区域)进行加工,只有黄金可以运输。应用程序和数据库也是如此 就PostgreSQL而言,您几乎可以在服务器上高效地执行任何操作。RDBMS擅长于复杂的查询。对于过程性需求,您可以从各种类型中进行选择:tcl、python、perl和更多。不过,我用的大多是 最坏的情况是重复出现
import psycopg2
import psycopg2.extras
from talib import func
import timeit
import numpy as np
with psycopg2.connect('dbname=xyz user=xyz') as conn:
with conn.cursor() as cur:
t0 = timeit.default_timer()
cur.execute('select distinct symbol from ohlc_900 order by symbol')
for symbol in cur.fetchall():
cur.execute('select c from ohlc_900 where symbol = %s order by ts', symbol)
ohlc = np.array(cur.fetchall(), dtype = ([('c', 'f8')]))
wma = func.WMA(ohlc['c'], 10)
# print(*symbol, wma[-1])
print(timeit.default_timer() - t0)
conn.close()
"""
if the period is 10
then we need 9 previous candles or 15 x 9 = 135 mins on the interval department
we also need to start counting at row number - (count in that group - 10)
For example if AAPL had 134 coins and current row number was 125
weight at that row will be weight = 125 - (134 - 10) = 1
10 period WMA calculations
Row no Weight c
125 1
126 2
127 3
128 4
129 5
130 6
131 7
132 8
133 9
134 10
"""
query2 = """
WITH
condition(sym, maxts, cnt) as (
select symbol, max(ts), count(symbol) from ohlc_900 group by symbol
),
cte as (
select symbol, ts,
case when cnt >= 10 and ts >= maxts - interval '135 mins'
then (row_number() over (partition by symbol order by ts) - (cnt - 10)) * c
else null
end as weighted_close
from ohlc_900
INNER JOIN condition
ON symbol = sym
WINDOW
w as (partition by symbol order by ts rows between 9 preceding and current row)
)
select symbol, sum(weighted_close)/55 as wma
from cte
WHERE weighted_close is NOT NULL
GROUP by symbol ORDER BY symbol
"""
with psycopg2.connect('dbname=xyz user=xyz') as conn:
with conn.cursor() as cur:
t0 = timeit.default_timer()
cur.execute(query2)
# for i in cur.fetchall():
# print(*i)
print(timeit.default_timer() - t0)
conn.close()