ORA-01013仅在第一次执行SELECT时

时间:2016-09-18 11:56:28

标签: java sql oracle spring-data query-optimization

我有一个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万行)。

任何想法都可能成为问题?

谢谢!

1 个答案:

答案 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)的本地分区索引中获益。