我的Oracle BBDD出了问题。一个查询消耗了大量的SGA,直到BBDD开始给出错误ORA-04031并且我必须重置它。
在AWR中,我可以在“可共享内存排序的SQL”中看到查询。查询在本节中出现很多次,每个不同的“或”,例如:
查询1:
...My Query... WHERE ( inc.ID =:"SYS_B_131"
OR inc.ID =:"SYS_B_132"
OR inc.ID =:"SYS_B_133"
OR inc.ID =:"SYS_B_134" )
查询2:
...My Query... WHERE ( inc.ID =:"SYS_B_131"
OR inc.ID =:"SYS_B_132"
OR inc.ID =:"SYS_B_133"
OR inc.ID =:"SYS_B_134"
OR inc.ID =:"SYS_B_135"
OR inc.ID =:"SYS_B_136"
OR inc.ID =:"SYS_B_137"
OR inc.ID =:"SYS_B_138" )
Etc等。
我的问题是,查询4“或”项目的内存消耗为3MB,查询为500“或”项目的内存消耗为1GB,¿这是正常的吗?
答案 0 :(得分:1)
我找到了问题。是一个Oracle Bug。在我的Oracle BBDD版本中,如果Query有很多绑定变量,则查询执行计划会消耗大量SGA(仅针对查询直到1.2Gb)。
我已经重写了Query以替换" IN" SubQuery的值列表,问题解决了。
答案 1 :(得分:0)
我不会称之为bug。这是甲骨文设定的一个相当明智的限制,善意防止单个查询阻塞大部分宝贵的SGA内存。 应用500" IN"列表谓词根本不是建议的练习(有或没有绑定)。而且,只需推动500" IN"单独使用子查询中的列表谓词在这里无济于事。 我们应该将所有这500个奇数ID存储在一个小表中并索引FK并应用EXISTS子查询,如 -
SELECT <col list> FROM MainTable inc
WHERE EXISTS (SELECT 1 FROM 500_IDTable inc2 inc.ID = inc2.ID);
虽然你没有共享修改后的Query / SubQuery,但我猜你应该这样做。
@ ibre5041 - 上面发布的查询已经使用bind var。实际上,绑定变量太多了。
Ildelian - 我们不应该使用CURSOR_SHARING = FORCE作为永久修复。应该使用'EXACT'代替。默认值为CURSOR_SHARING = EXACT。
了解原因https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:4608916500346512056
使用cursor_sharing = force已经显示出数据库在其库缓存中受到文字(即非重入SQL)困扰的好处。
在你的情况下,CURSOR_SHARING = FORCE根本没有任何意义,因为你似乎已经在使用绑定变量了。
请考虑更改CURSOR_SHARING = EXACT。