【发布时间】:2016-09-18 11:56:27
【问题描述】:
我有一个 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 万行)。
有什么想法可能是问题吗?
谢谢!
【问题讨论】:
-
让有数据库的人知道如何分析执行计划和创建缺失的索引。这也可能有助于调整数据库设计。像
a.ID = substr(ca.ARTICLE, 0, 8)这样使用 substr 会阻止使用普通索引。您可能会摆脱功能索引,但我强烈建议您尽可能调整数据库设计。 -
您能否验证该表在哪个字段上进行了分区?如果它在一个字段上分区(例如“action_month”),那么当您根据此类字段限制您的选择时,查询将仅从几个分区中检索数据,而不是全表扫描。
-
表 CLIENT_ARTICLES 有以下分区: PARTITION BY RANGE ("ACTION_DATE") INTERVAL (NUMTODSINTERVAL (1, 'DAY')) (PARTITION "CLIENT_ARTICLES" VALUES LESS THAN (TO_DATE(' 2014-01 -01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) 段创建延迟
-
我知道数据库设计一团糟,但真正的问题是 java 进程在第一次执行时被阻塞。
标签: java sql oracle spring-data query-optimization