我有一个查询
select a.id,
a.code,
h.history_id
from a
join h
on h.object_id = a.id
and h.level = 'Level1'
and h.class_id in ('class1', 'class2');
及其执行计划:
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 340 |108889 | 794224 | 00:00:32 |
| *1 | HASH JOIN | | 340 |108889 | 794224 | 00:00:32 |
| 2 | TABLE ACCESS STORAGE FULL | a | 340 | 39314 | 2 | 00:00:01 |
| 3 | PARTITION RANGE ALL | | 274564| 54855 | 69422 | 00:00:32 |
| *4 | TABLE ACCESS STORAGE FULL | h | 274564| 54855 | 69422 | 00:01:14 |
-----------------------------------------------------------------------------------
*1 - access("a"."id" = "h"."object_id")
*4 - storage ("h"."level" = 'Level1' and ("h"."class_id" = 'class1' or "h"."class_id" = 'class2'))
*4 - filter ("h"."level" = 'Level1' and ("h"."class_id" = 'class1' or "h"."class_id" = 'class2'))
在表上也有索引-在表a(id)上,在表h(object_id,level,class_id)上有复合索引。 统计信息也被收集。
表a包含约340条记录,表h包含约10亿条记录。 结果查询返回约200行
尽管表h的索引中的所有列都在联接条件下使用,但根据计划,在列级别和class_id上没有访问谓词。 我不明白这种解决方案。
我希望至少h.level处于访问谓词中。 有什么解决办法吗?还是某种查询重写?
答案 0 :(得分:0)
基于该语句,查询结果只有200行,应使用索引。
使用综合数据(最简单的情况,OBJECT_ID
在表H
中是唯一的),您应该看到此执行计划
Plan hash value: 3146900768
--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 200 |00:00:00.04 | 40 | 4 |
| 1 | NESTED LOOPS | | 1 | 2 | 200 |00:00:00.03 | 40 | 4 |
| 2 | NESTED LOOPS | | 1 | 340 | 200 |00:00:00.02 | 36 | 3 |
| 3 | TABLE ACCESS FULL | A | 1 | 340 | 340 |00:00:00.01 | 3 | 0 |
|* 4 | INDEX RANGE SCAN | HIX | 340 | 1 | 200 |00:00:00.02 | 33 | 3 |
| 5 | TABLE ACCESS BY INDEX ROWID| H | 200 | 1 | 200 |00:00:00.01 | 4 | 1 |
--------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("H"."OBJECT_ID"="A"."ID" AND "H"."LEVEL_ID"='Level1')
filter(("H"."CLASS_ID"='class1' OR "H"."CLASS_ID"='class2'))
因此,请检查您的Oracle版本(我在12.1上)
验证统计信息是否正确。
检查系统统计信息。
检查您的Oracle CBO参数是否正常。