Oracle SQL索引查询100%cpu使用率
我正在运行一个相对简单的查询Oracle SQL索引查询100%cpu使用率,sql,oracle,Sql,Oracle,我正在运行一个相对简单的查询 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
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\u type
是一个varchar2(50个字符)
,其余的是number(10)
,如果它有任何意义的话
invoice\u confirm
和confirm
表包含在索引中,并且此查询的执行计划中没有可见的完整表扫描
这个查询执行得不多,但占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
收集相关表上的优化器统计信息,并调查统计信息丢失的原因
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实现良好性能至关重要。注释使用的动态统计信息:动态采样(级别=2)
意味着存在缺少优化器统计信息的表。除非表格是在最后一天内创建的,否则这种情况永远不会发生
Oracle自动收集过时和丢失的统计信息。检查作业是否正在使用此查询运行。如果最近没有行,请让DBA重新启用该任务
select *
from dba_optstat_operations
where operation like '%auto%'
order by start_time desc;
自动任务对于大多数表来说已经足够好了。但是,如果有一个更新了很多行的大批量过程,那么在作业完成后应立即手动收集统计信息。您有哪些索引?四个表总共有多少行(粗略估计)?另外,请张贴执行计划。我怀疑没有完整的表格扫描看到所有这些
=代码>。除了您正在搜索的可能性之外,无法通过列出所有可能性来更改它们?计划:发票上的索引\u确认。发票\u id,所有id。在那些confirm.previous等上没有索引。我要说的是,您对结果集中包含的每个confirm\u v
记录进行排序(CPU密集型操作)。如果要排序的数量很大,则会占用大量CPU。顺便说一句,orderby
在线性日志时间内进行完全排序,而min
只在线性时间内对集合进行完全扫描;你可以考虑使用它。要检查是否是这种情况,请尝试在子查询中注释出orderby
部分,看看它是否运行得更快。