如何针对1746行优化此查询需要30秒?

时间:2010-07-12 01:01:33

标签: sql oracle optimization plsql query-optimization

查询:

SELECT A.USER_ID, A.ROLE_ID, C.SUBGROUP, MAX(A.STATUS_ID)
                 FROM USER_ROLE A, USER B, ROLE C
                WHERE A.ROLE_ID = C.ROLE_ID
                  AND C.GROUP_ID = 3
                  AND A.USER_ID = B.USER_ID
                  AND B.TEMPLATE_IND = 'N'
                  AND B.ONAP_PARTCODE IS NULL
                  AND A.PARTCODE ='005'
                GROUP BY A.PARTCODE,
                         A.USER_ID,
                         A.ROLE_ID,
                         C.SUBGROUP;

解释计划:

--------------------------------------------------------------------------------
| Id  | Operation                      | Name               | Rows  | Bytes | Co
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                    |     1 |    74 |
|   1 |  HASH GROUP BY                 |                    |     1 |    74 |
|   2 |   NESTED LOOPS                 |                    |     1 |    74 |
|   3 |    NESTED LOOPS                |                    |    56 |  3024 |
|   4 |     TABLE ACCESS BY INDEX ROWID| ROLE               |     8 |   240 |
|*  5 |      INDEX RANGE SCAN          | N_ROLE_IDX2        |     8 |       |
|   6 |     TABLE ACCESS BY INDEX ROWID| USER_ROLE          |     7 |   168 |
|*  7 |      INDEX RANGE SCAN          | N_USER_ROLE_IDX6   |     7 |       |
|   8 |    REMOTE                      | MV_PT_USER         |     1 |    20 |
--------------------------------------------------------------------------------

5 个答案:

答案 0 :(得分:4)

我重写了你的查询以使用ANSI-92语法:

  SELECT A.USER_ID, A.ROLE_ID, C.SUBGROUP, MAX(A.STATUS_ID)
    FROM USER_ROLE a
    JOIN USER b ON b.user_id = a.user_id
               AND b.template_ind = 'N'
               AND b.onap_partcode IS NULL
    JOIN ROLE c ON c.role_id = a.role_id
               AND c.group_id = 3
   WHERE a.PARTCODE ='005'
GROUP BY a.USER_ID, a.ROLE_ID, c.SUBGROUP, a.PARTCODE;

suggest the following covering indexes来说,这不是更快,对我来说更清楚:

CREATE INDEX ur_idx ON USER_ROLE (user_id, role_id, partcode) COMPUTE STATISTICS;
CREATE INDEX u_idx ON USER (user_id, template_ind) COMPUTE STATISTICS;
CREATE INDEX r_idx ON ROLE (role_id, group_id) COMPUTE STATISTICS;

答案 1 :(得分:2)

计划中的ROWS估计以1结束,而不是在1700附近。 MV_PT_USER上的“远程”操作很有意思。看起来优化器假设该操作将返回一行(或者可能为零),即使没有过滤。

收集该对象的一些统计信息可能会告诉oracle它可能返回多少行,并建议与优化器不同的计划。

答案 2 :(得分:0)

如果不了解有关您的表架构和索引的详细信息,那么很难给出正确的建议。

它可能没什么用,但我确实看到你的GROUP BY子句中的A.PARTCODE不需要。

答案 3 :(得分:0)

您的查询需要30秒。现在我们需要知道这些30秒花在哪里。提供的信息几乎没有,所以是时候跟踪查询的运行了。

以下是有关如何收集所需信息的一些快速信息:http://forums.oracle.com/forums/thread.jspa?messageID=1812597

此致 罗布。

答案 4 :(得分:0)

我认为你最好研究什么是内连接,右连接和左连接

如果所有表都有公共字段而不是null,那么您可以考虑处理最少行数的内部连接