我在公司遇到的问题是 - 我们的程序速度不够快。更具体地说,我们是电信公司,这个程序处理我们城市每个手机用户的电话/互联网服务交易。由于iphone用户下载内容的数量太多,我们的程序无法足够快地处理它们。
情况是,用户进行的交易金额是我们程序处理的交易的两倍。程序的大部分运行时间都由数据库事务控制。
我通过互联网搜索并浏览了一些网站(例如:http://www.javaperformancetuning.com/tips/rawtips.shtml),讨论了数据库中的Java性能,但我找不到适合我们的建议。
这些建议不适用/已经使用过,例如:
1。使用预备陈述。使用参数化SQL
已经使用过准备好的声明。每次都会通过清除参数和设置参数使用不同的参数。
2。调整SQL以最小化返回的数据(例如,不是'SELECT *')。
当然,已经使用过了。
第3。使用连接池。
我们在程序执行期间保持一个连接。我怀疑汇集无法解决问题,因为我们的程序充当1个用户,因此并发访问DB没有问题。如果你们有人认为合并是好的,请告诉我原因。感谢。
4。尝试将查询和批量更新结合起来。
不能这样做。每个查询/插入/更新都取决于数据库的信息。例如,我们在DB中查找客户端的信息,如果我们找不到他的用法,我们会将用法插入到DB中,否则我们会更新。
5。完成后关闭资源(连接,语句,结果集)
不确定
6。选择最快的JDBC驱动程序。
我不知道。我在互联网上搜索可用的驱动程序类型,我很困惑。我们使用oracle.jdbc.driver.OracleDriver
,我们使用thin而不是oci,这就是我所知道的。另外,我们的程序是两层方式(java< - > oracle)
7。关闭自动提交
已经完成了。
期待任何帮助。
答案 0 :(得分:10)
<强> 4。尝试将查询和批量更新结合起来。
不能这样做。一切 查询/插入/更新取决于 数据库的信息。例如, 我们查找客户端的数据库 信息,如果我们找不到他的 用法,我们将用法插入DB, 否则我们会更新。
如果您是从Java应用程序执行此操作,则可以通过一次往返在数据库中执行此操作来提高性能。有几种方法:
1)使用SQL MERGE语句
2)编写存储过程来执行插入或更新逻辑,然后从Java调用它。
我假设从你所说的那一刻起你的Java逻辑就像这样:
// Pseudocode
execute SQL 'select count(*) from mytable where id=?'
if result = 0 then
execute SQL 'insert into mytable (id,a,b,c) values (?,?,?,?)';
else
execute SQL 'update mytable set a=?, b=?, c=? where id=?';
end if;
这意味着2次单独往返数据库:一次检查记录是否存在,另一次是根据需要插入或更新。
替代方案是:
1)使用SQL MERGE语句:
// Pseudocode
execute SQL 'merge into mytable t using (select ? id, ? a, ? b, ? c from dual) s
on (t.id = s.id)
when matched then update set t.a = s.a, t.b = s.b, t.c = s.c
when not matched then insert (id, a, b, c)
values (s.id, s.a, s.b, s.c)';
MERGE语句起初有点令人生畏,特别是在这样的情况下你必须使用Oracle的“双”表。
2)使用存储过程:
// Pseudocode
execute SQL 'begin mytable_package.insert_or_update
(p_id => ?, p_a => ?, p_b => ?, p_c => ?); end;'
存储过程在名为mytable_package的包中看起来像
procedure insert_or_update (p_id mytable.id%type
,p_a mytable.a%type
,p_b mytable.a%type
,p_c mytable.a%type
)
is
begin
update mytable
set a = p_a, b = p_b, c = p_c
where id = p_id;
if sql%rowcount = 0 then
insert into mytable (id, a, b, c) values (p_id, p_a, p_b, p_c);
end if;
end;
答案 1 :(得分:6)
检查索引!!! 错误的更新性能可能是外键约束的结果,其中外键上的索引在引用表上缺失。
4)尝试组合查询和批处理 更新。
不能这样做。一切 查询/插入/更新取决于 数据库的信息。例如, 我们查找客户端的数据库 信息,如果我们找不到他的 用法,我们将用法插入DB, 否则我们会更新。
我想到了两件事:
执行UPDATE语句并检查ExecuteUpdate()的结果;仅当它为零时,执行INSERT。为您保存一个SELECT语句。
始终(可能批量)插入中间表,稍后使用MERGE语句更新您的使用表。
5)完成后关闭资源(Connections,Statements,ResultSet)
尽可能长时间保持连接打开(即永久关闭服务器),准备一次PreparedStatement并重复使用。
在写入数据库之前进行一些聚合。现在生成交易的手机用户可能会在几秒钟内生成另一个交易。使用哈希表来聚合当前使用情况,并在一分钟左右后将其写入数据库。
答案 2 :(得分:4)
获取Professional Oracle Programming。
的副本2005年似乎有点偏旧,但在优化性能方面,Oracle并没有大幅改变。我自己有这本书,并且已经使用它的建议来加速许多应用程序看似棘手的性能问题。得到它。阅读。做吧。
那么您在等待快递时可以做些什么?
这应该足以让你牢牢掌握失败的原因以及解决方法。
答案 3 :(得分:3)
首先你需要DBA在你身边来告诉你实际花费的时间。您可以在客户端快速闪电,并且在设置关键索引之前仍然需要很长的事务处理时间。
我使用Java + Oracle已经八年了,但我没有找到oci驱动程序(在DLL中使用本机驱动程序)比使用瘦驱动程序(所有用Java编写)快得多。
快速解决这个问题,可以生成一个1000或10000个事务的文本文件,让“SQLLDR”将批处理注入数据库。也许更多。正确调用SQLLDR是最快的事情,它会让你有时间正确地执行它。
答案 4 :(得分:0)
您是否为每次执行启动JVM的新实例?您能否详细说明应用程序的性质(即如何调用它,触发调用的内容等)。根据您的描述,它听起来并不像Java和DB问题。听起来好像是某种数据库索引问题或其他设计问题。您正在使用的SQL命令的性质是什么?您是否计划或分析了这些电话,看看是否有些电话比其他电话要长?
答案 5 :(得分:0)
您可以将工作负载划分为使用多个会话到数据库吗?有很多往返数据库的往返导致延迟。如果表的结构正确,它们可以毫无问题地处理多个并发插入/更新(检查重插入表的INITRANS属性是否与执行插入的并发会话数相同)。我认为这将是赢得应用性能最简单的方法。 正在使用哪个版本的数据库? 你能得到ADDM报告吗?他们可以立即告诉您 - 数据库中的问题是什么 - 如果有的话。 应用服务器有足够的CPU资源吗?如果没有,这是将负载分成多个会话的另一个原因,在这种情况下分成多个应用服务器。 如果没有statspack报告或 - 最好是 - ADDM报告,很难说出问题所在。
我希望这有帮助, 罗纳德。
答案 6 :(得分:0)
如果您希望将DBA的参与保持在最低限度,您至少可以要求登录以访问在测试服务器上运行的Oracle Enterprise Manager。在OEM中,您实际上可以看到哪些操作需要很长时间。 OEM还会尝试通过建议提高性能的方法来帮助您,例如添加索引或更改查询结构。希望OEM至少能为您提供可靠的理由,要求DBA进一步参与。