求助:内存泄露、速度巨慢

core 2003-12-04 11:49:11
RH Linux 7.2 + Oracle 8.17 + ESQL for c
一、程序运行了一段时间(大约一个月),出现SGA内存分配失败。程序每笔交易都会做commit或rollback,这是肯定的
不过每分钟都有数据库查询程序运行,时间很短,查询完成就退出
有个表当中有大约88000条数据,执行delete from xxxx where substrb(key, n, m) = ....巨慢
请高手分析一下什么原因。分不够再加,一次只能给这么多
谢谢!
...全文
36 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
yjmfdm 2003-12-06
  • 打赏
  • 举报
回复
分批delete
zyq2000 2003-12-05
  • 打赏
  • 举报
回复
怎么把SGA加大。
beckhambobo 2003-12-05
  • 打赏
  • 举报
回复
http://search.csdn.net/expert/topic/61/6101/2002/7/26/903782.htm
core 2003-12-04
  • 打赏
  • 举报
回复
以小批数据为单位,批量提交,尽可能减小回滚段的占用
--------------------
在一个delete当中怎么实现?
core 2003-12-04
  • 打赏
  • 举报
回复
给substrb(key, n, m)加索引也想过,但会不会同样是很长时间,而且这个delete操作也只是维护时临时用用的
还有,什么是function index
对内存泄漏的原因可能是什么?比如说游标不释放等等...
LGQDUCKY 2003-12-04
  • 打赏
  • 举报
回复
给substrb(key, n, m) 加上索引,顺便把SGA加大。
leecooper0918 2003-12-04
  • 打赏
  • 举报
回复
delete from xxxx where substrb(key, n, m) = ....巨慢
----------------------------------------------------
你这条语句不可能快,因为你用了substrb函数,就像你用
select * from xxx where substrb(key, n, m) = ...
一样,只要key列上没有建立function index,执行的就是全表
扫描.

改进的办法:
1. 启用一个私有的大的回滚段
2. 以小批数据为单位,批量提交,尽可能减小回滚段的占用.

查内存是否泄漏:
select * from v$SGASTAT 能看到 SGA的具体使用信息.

看看其中的 shared pool miscellaneous是否很大。


还有: 操作系统和数据库如果有补丁程序,要及时打补丁。

yujiabian 2003-12-04
  • 打赏
  • 举报
回复
索引的存在会影响到数据的insert,update,delete操作,不知道你的具体情况是什么?
leecooper0918 2003-12-04
  • 打赏
  • 举报
回复

function index:就是给基于列的函数操作建立索引.
例如你有大量的诸如instr,substr之类的操作,就可以考虑建立
函数索引。但是使用基于函数的索引会带来下面的问题:

. 不能完全限制活跃表上特定列上使用的函数 ;

. 需要额外的存储空间,可能会导致 I/O冲突 ;

. 撤销表时,将撤销更多的索引, 增大了管理代价.

关于批量删除,我可以给你一个例子,这个例子来自metalink,但是
效率不高,并且会产生大量重做日志.

CREATE OR REPLACE PROCEDURE delete_tab
(tablename IN VARCHAR2,
empno IN NUMBER,
nrows IN NUMBER)
IS
sSQL1 VARCHAR2(2000);
sSQL2 VARCHAR2(2000);
nCount NUMBER;

BEGIN

nCount := 0;
sSQL1:='delete from '|| tablename ||
' where ROWNUM < ' || nrows || ' and empno=' || empno;
sSQL2:='select count(ROWID) from ' || tablename ||
' where empno= ' || empno;

LOOP

EXECUTE IMMEDIATE sSQL1;

EXECUTE IMMEDIATE sSQL2 INTO nCount;

DBMS_OUTPUT.PUT_LINE('Existing records: ' || to_char(ncount));

commit;

EXIT WHEN nCount = 0;

END LOOP;

END delete_tab;
/

还有其他的方法:
1. SET TRANSACTION USE ROLLBACK SEGMENT RBSNAME;
DELETE FROM TBNAME where ...
COMMIT;

这种方法就是我上面提到的"启用一个大的私有回滚段",但是
这种方法很可能引发"snapshot too old"的错误。因此最好在
并发事务比较少的情况下使用。

2. asktom.oracle.com上推荐的方法:

case1:
create table new_table unrecoverable as select * from old_table where ....;
drop table old_table;
rename new_table to old_table;
create index old_table_idx1 on old_table(c1,c2) unrecoverable parallel 5;
.....

NO log on that, just move the data to a new table, drop/rename old/new,
create indexes as fast as possible without log.

case2:
partition the data, do a parallel delete. Each partition will use its own
rollback segment, each will run in parallel.

case3:
partition the data so that you can do a DROP partition instead of
DELETE

dxxfun 2003-12-04
  • 打赏
  • 举报
回复
在使用函数的检索列,索引是失效的。

17,086

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧