我有一个java程序,它使用Spring框架中的JdbcTemplate类在我的Oracle数据库上执行各种SELECT查询。
每次我在长时间停顿(1-2天)后运行此程序时,它仍会被阻止到特定查询,并且在等待ORA-01013错误十分钟后我收到超时异常。如果我再次运行该程序,它将执行正常,没有任何错误。
具体查询是:
SELECT ca.ARTICLE as article, r.COUNTRY as country, count(1) as total
FROM CLIENT_ARTICLES ca
INNER JOIN ARTICLES aa ON a.ID = substr(ca.ARTICLE, 0, 8)
INNER JOIN SEAZON_P sp ON sp.PARAM = 'paramS1' AND substr(a.id, 1, 1) = sp.seazon
INNER JOIN REGISTER r ON r.id = ca.CLIENT_ID
WHERE ca.ACTION_DATE > sysdate - 5 AND ca.ACTION = 'I'
GROUP BY ca.ARTICLE, r.COUNTRY
ORDER BY ca.ARTICLE, r.COUNTRY;
此查询的解释计划:
Plan hash value: 3771965889
-------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 11 | 759 | 71934 (2)| 00:14:24 | | |
| 1 | SORT ORDER BY | | 11 | 759 | 71934 (2)| 00:14:24 | | |
| 2 | HASH GROUP BY | | 11 | 759 | 71934 (2)| 00:14:24 | | |
| 3 | NESTED LOOPS | | 11 | 759 | 71932 (2)| 00:14:24 | | |
| 4 | NESTED LOOPS | | 40 | 1920 | 71932 (2)| 00:14:24 | | |
| 5 | NESTED LOOPS | | 2 | 78 | 71928 (2)| 00:14:24 | | |
| 6 | PARTITION RANGE ITERATOR | | 2 | 58 | 71924 (2)| 00:14:24 | KEY |1048575|
|* 7 | TABLE ACCESS FULL | CLIENT_ARTICLES | 2 | 58 | 71924 (2)| 00:14:24 | KEY |1048575|
| 8 | TABLE ACCESS BY INDEX ROWID| REGISTER | 1 | 10 | 2 (0)| 00:00:01 | | |
|* 9 | INDEX UNIQUE SCAN | PK_REGISTER | 1 | | 1 (0)| 00:00:01 | | |
|* 10 | INDEX RANGE SCAN | PK_ARTICLES | 20 | 180 | 2 (0)| 00:00:01 | | |
|* 11 | INDEX UNIQUE SCAN | SEAZON_P_PK | 1 | 21 | 0 (0)| 00:00:01 | | |
-------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
" 7 - filter(""CA"".""ACTION_DATE"">SYSDATE@!-3 AND ""CA"".""ACTION""='I')"
" 9 - access(""R"".""ID""=""CA"".""CLIENT_ID"")"
" 10 - access(""A"".""ID""=SUBSTR(""CA"".""ARTICLE"",0,8))"
" 11 - access(""SP"".""SEAZON""=SUBSTR(""CA"".""ID"",1,1) AND ""A"".""PARAM""='paramS1')"
执行查询的java代码:
public List<ArticleDTO> select(final String param) {
List<ArticleDTO> articleList;
String[] queryArgs = { param};
super.jdbcTemplate.setFetchSize(20000);
articleList = super.jdbcTemplate.query(SELECT_ARTICLES, queryArgs, this.articleRowMapper);
return articleList;
}
查询返回超过80,000个结果,但表格非常大(> 1000万行)。
任何想法都可能成为问题?
谢谢!
答案 0 :(得分:1)
&#34;我在等待10分钟后得到超时异常 ORA-01013错误。如果我再次运行该程序将没有执行罚款 任何错误&#34;
ORA-01013的含义是用户请求取消当前操作。所以最有可能的解释是你的Spring层被配置为在十分钟后超时请求。但它第二次成功,因为相关数据存储在数据库内存和/或操作系统缓存中。
那么你可以做些什么来改善问题呢?钝器是检查超时参数并增加它。这将是最快的胜利,但可能存在争议。减少执行时间是可取的,但需要更长时间,因为您需要进行一些调查和测试。
你问题的显着之处在于:
&#34;查询返回80.000以上的结果,但表格非常大(> 10万行)。&#34;
解释计划中的rows
数字远远不及这个数字。优化器认为您对CLIENT_ARTICLE的过滤器将返回每个分区两行,这对于这样的大型表来说似乎可疑。所以首先要检查的是桌子的新鲜感。统计。准确的统计数据有助于优化者找到一个好的执行计划。
另一件事是查询在范围内的分区上运行全表扫描(由ca.ACTION_DATE > sysdate - 5
限制,因此有五个或六个分区)。如果表格很宽(很多列),那么当你需要的只是投影中的ARTICLE和过滤器中的ACTION时,这是一项昂贵的操作。如果这是一个你经常运行的查询,你可以从(ARTICLE,ACTION)的本地分区索引中获益。