我有一些PL / SQL代码,我认为可能有内存泄漏。每次我运行它似乎运行速度比以前慢,即使现在我正在减少输入大小。我怀疑的代码是使用bulk-collect从游标填充数组,类似这样的
open c_myCursor(in_key);
fetch c_myCursor bulk collect into io_Array; /*io_array is a parameter, declared as in out nocopy */
close c_myCursor;
我不确定如何检查导致这种减速的原因。我知道Oracle中有一些表可以跟踪这种内存使用情况,但是我不确定是否可以查看这些表并找回我的代码所做的有用的东西。
此外,我尝试退出会话并在大约10-15分钟后重新登录,但仍然很慢。
Oracle版本是10.2
事实证明是其他数据库活动。 DBA决定在我开始更改和测试代码的同时运行一些大型插入和更新作业。我怀疑我的代码是根本原因,因为我没有被告知其他工作正在运行(而且我只听说过其他工作,因为它完全冻结了一切,所有其他开发人员都生气了)。这可能就是为什么我的代码变得越来越慢。
有没有办法以编程方式找到它,例如查询插入/更新大量数据的会话,以防DBA忘记在下次执行此操作时告诉我?
答案 0 :(得分:2)
“我尝试退出会话并在大约10-15分钟后重新登录,但仍然很慢。”
假设您在* nix平台上使用传统的专用连接,这几乎可以排除任何内存泄漏。当您建立与数据库的新连接时,oracle将为它分离一个新进程,并且所有PGA内存都属于该进程,当会话断开并终止进程时,它将被释放(由操作系统)。 / p>
如果您使用的是共享服务器连接,则会话将使用属于该进程的内存以及共享内存。这可能更容易受到任何内存泄漏问题的影响。
Windows不能以完全相同的方式工作,因为它不为每个会话分配单独的进程,而是在单个Oracle进程下有一个单独的线程。同样,我怀疑这会更容易受到内存泄漏的影响。
我通常首先查找其他问题,并且可能从查询底层c_myCursor开始。也许它必须通读更多旧数据来获取新数据?
答案 1 :(得分:2)
v $ sessmetric是一种快速查看每个会话使用的资源的方法 - cpu,physical_reads,logical_reads,pga_memory等。
答案 2 :(得分:0)
http://www.dba-oracle.com/t_plsql_dbms_profiler.htm描述了DBMS_PROFILER。我想你的代码中最慢的部分可以连接到内存泄漏。无论如何,如果你回到原来的问题,它变得越来越慢,那么首先要做的是看看什么是慢,然后假设内存泄漏。
听起来你执行之间没有提交,重做日志越来越大。这可能是数据库需要提供读取一致性的原因。
您还可以检查企业管理控制台。你用的是哪个版本?永远不要使用XE进行开发,因为据我所知,专业版可以用于开发目的。企业管理控制台甚至可以为您提供建议。也许它可以告诉你一些关于PLSQL问题的聪明方法。
答案 3 :(得分:0)
如果您的查询返回非常数据,您的收藏可能会变得非常大,比如10 000 000条记录 - 这可能是可疑内存使用的重点。
您可以通过记录批量收集的集合的大小来检查此问题。如果它大于10 000(只是一个粗略的估计,这取决于当然的数据),你可以考虑拆分并使用部分数据,如下所示:
declare
cursor cCur is select smth from your_table;
--
type TCur is table of cCur%rowtype index by pls_integer;
--
fTbl TCur;
begin
open cCur;
loop
fTbl.delete;
fetch cCur bulk collect into fTbl limit 10000;
exit when cCur%notfound;
for i in 1 .. fTbl.count loop
--do your wok here
end loop;
end loop;
close cCur;
end;
既然你说这个表是在nocopy中声明的,我知道你不能直接重写这样的逻辑,但只考虑方法,也许这可以帮助你。