【问题标题】:Oracle SQL indexed query 100% cpu usageOracle SQL 索引查询 100% cpu 使用率
【发布时间】:2018-05-01 13:19:38
【问题描述】:

我正在运行一个相对简单的查询

SELECT * FROM confirm_v c
JOIN person p ON c.created_by=p.id
INNER JOIN invoice_confirm ic ON ic.confirm_id=c.id
WHERE c.id = (SELECT id FROM 
                 (SELECT c2.id FROM confirm c2
                  JOIN invoice_confirm ic2 ON ic2.confirm_id=c2.id
                  WHERE ic2.invoice_id=11954081
                  AND c2.previous=0
                  AND c2.canceled=0
                  AND c2.confirm_type='INVOICE'
                  ORDER BY c2.id)
              WHERE rownum=1);

这会导致 rdb 使用 100% 的 cpu。 confirm_typevarchar2(50 char),其余的是 number(10),如果这意味着什么。

invoice_confirmconfirm 表被索引覆盖,并且在此查询的执行计划中没有可见的全表扫描。

此查询执行的次数不多,但占总 cpu 使用率的近 100%。任何想法都表示赞赏。

编辑: 查询的文本解释计划。

EXPLAIN PLAN FOR ...
SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());
Plan hash value: 1705859247


------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                      | Name                        | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                               |                             |     1 |    69 |    10   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                                  |                             |     1 |    69 |    10   (0)| 00:00:01 |
|   2 |   NESTED LOOPS                                 |                             |     1 |    69 |    10   (0)| 00:00:01 |
|   3 |    NESTED LOOPS                                |                             |     1 |    57 |     7   (0)| 00:00:01 |
|   4 |     NESTED LOOPS                               |                             |     1 |    30 |     5   (0)| 00:00:01 |
|   5 |      TABLE ACCESS BY INDEX ROWID               | CONFIRM                     |     1 |    24 |     3   (0)| 00:00:01 |
|*  6 |       INDEX UNIQUE SCAN                        | PK_CONFIRM                  |     1 |       |     2   (0)| 00:00:01 |
|*  7 |        COUNT STOPKEY                           |                             |       |       |            |          |
|   8 |         VIEW                                   |                             |     4 |    52 |    27   (4)| 00:00:01 |
|*  9 |          SORT ORDER BY STOPKEY                 |                             |     4 |   132 |    27   (4)| 00:00:01 |
|  10 |           NESTED LOOPS                         |                             |     4 |   132 |    26   (0)| 00:00:01 |
|  11 |            NESTED LOOPS                        |                             |    11 |   132 |    26   (0)| 00:00:01 |
|  12 |             TABLE ACCESS BY INDEX ROWID BATCHED| INVOICE_CONFIRM             |     3 |    36 |     4   (0)| 00:00:01 |
|* 13 |              INDEX RANGE SCAN                  | FKI_INVOICE_CONFIRM_INVOICE |     2 |       |     3   (0)| 00:00:01 |
|* 14 |             INDEX UNIQUE SCAN                  | PK_CONFIRM                  |     1 |       |     1   (0)| 00:00:01 |
|* 15 |            TABLE ACCESS BY INDEX ROWID         | CONFIRM                     |     1 |    21 |     2   (0)| 00:00:01 |
|* 16 |      INDEX RANGE SCAN                          | FKI_INVOICE_CONFIRM_CONFIRM |     1 |     6 |     2   (0)| 00:00:01 |
|  17 |     TABLE ACCESS BY INDEX ROWID                | PERSON                      |     1 |    27 |     2   (0)| 00:00:01 |
|* 18 |      INDEX UNIQUE SCAN                         | PK_KASUTAJA                 |     1 |       |     1   (0)| 00:00:01 |
|* 19 |    INDEX RANGE SCAN                            | FKI_INVOICE_CONFIRM_CONFIRM |     1 |       |     2   (0)| 00:00:01 |
|  20 |   TABLE ACCESS BY INDEX ROWID                  | INVOICE_CONFIRM             |     1 |    12 |     3   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   6 - access("CONFIRM"."ID"= (SELECT "ID" FROM  (SELECT "C2"."ID" "ID" FROM "INVOICE_CONFIRM" "IC2","CONFIRM" "C2" 
              WHERE "IC2"."CONFIRM_ID"="C2"."ID" AND "C2"."CANCELED"=0 AND "C2"."PREVIOUS"=0 AND "C2"."CONFIRM_TYPE"='INVOICE' AND 
              "IC2"."INVOICE_ID"=11954081 ORDER BY "C2"."ID") "from$_subquery$_006" WHERE ROWNUM=1))
   7 - filter(ROWNUM=1)
   9 - filter(ROWNUM=1)
  13 - access("IC2"."INVOICE_ID"=11954081)
  14 - access("IC2"."CONFIRM_ID"="C2"."ID")
  15 - filter("C2"."CANCELED"=0 AND "C2"."PREVIOUS"=0 AND "C2"."CONFIRM_TYPE"='INVOICE')
  16 - access("IC"."CONFIRM_ID"="CONFIRM"."ID")
  18 - access("CONFIRM"."CREATED_BY"="P"."ID")
  19 - access("IC"."CONFIRM_ID"="CONFIRM"."ID")

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - 2 Sql Plan Directives used for this statement

【问题讨论】:

  • 你有什么索引?所有四个表有多少行(粗略估计)?另外,请发布执行计划。
  • 我怀疑没有看到所有!= 的全表扫描。不可能通过列出所有可能性来更改它们,但您正在搜索的可能性除外?
  • invoice_confirm.invoice_id 上的索引,所有 id。那些确认.previous 等没有索引。
  • 我会说您对包含在结果集中的每条confirm_v 记录进行排序(CPU 密集型操作)。如果要排序的数量很大,它将是 CPU 密集型的。顺便说一句,order by 在线性对数时间内进行完全排序,而min 在线性时间内对集合进行完全扫描;你可以考虑使用它。要检查是否是这种情况,请尝试注释掉子查询中的order by 部分,看看它是否运行得更快。

标签: sql oracle


【解决方案1】:

收集有关表的优化器统计信息并调查统计信息缺失的原因。

begin
    dbms_stats.gather_table_stats(user, 'CONFIRM');
    dbms_stats.gather_table_stats(user, 'INVOICE_CONFIRM');
    dbms_stats.gather_table_stats(user, 'PERSON');
end;
/

优化器统计信息对于 Oracle 获得良好性能至关重要。注释dynamic statistics used: dynamic sampling (level=2) 暗示有些表缺少优化器统计信息。除非表是在最后一天创建的,否则这种情况永远不会发生。

Oracle 自动收集过时和缺失的统计信息。检查作业是否正在使用此查询运行。如果没有最近的行,请让您的 DBA 重新启用该任务。

select *
from dba_optstat_operations
where operation like '%auto%'
order by start_time desc;

自动任务对于大多数表来说已经足够了。但是,如果有一个更新大量行的大型批处理过程,则应在作业完成后立即手动收集统计信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-20
    • 2020-10-08
    • 1970-01-01
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    相关资源
    最近更新 更多