SQL高可共享内存

时间:2016-07-28 13:57:28

标签: oracle oracle11g

我的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,¿这是正常的吗?

2 个答案:

答案 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。