我有一个查询,它在做解释计划时给我全表扫描,所以你能告诉我如何摆脱它。
输出:
|* 9 | INDEX UNIQUE SCAN | GL_PERIODS_U1 | 1 | | | 1 (0)|
|* 10 | TABLE ACCESS FULL | GL_PERIODS | 12 | 372 | | 6 (0)|
|* 11 | TABLE ACCESS BY INDEX ROWID | GL_JE_HEADERS | 1 | 37 | | 670 (0)|
|* 12 | INDEX RANGE SCAN | GL_JE_HEADERS_N2 | 3096 | | | 11 (0)|
|* 13 | TABLE ACCESS BY INDEX ROWID | GL_JE_BATCHES | 1 | 8 | | 2 (0)|
|* 14 | INDEX UNIQUE SCAN | GL_JE_BATCHES_U1 | 1 | | | 1 (0)|
|* 15 | INDEX RANGE SCAN | GL_JE_LINES_U1 | 746 | | | 4 (0)|
| 16 | TABLE ACCESS FULL | GL_CODE_COMBINATIONS | 1851K| 30M| | 13023 (1)|
我的查询:
explain plan for
select cc.segment1,
cc.segment2,
h.currency_code,
SUM(NVL(l.accounted_dr,0) - NVL(l.accounted_cr,0))
from gl_code_combinations cc
,gl_je_lines l
,gl_je_headers h
,gl_je_batches b
,gl_periods p1
,gl_periods p2
where cc.code_combination_id = l.code_combination_id
AND b.je_batch_id = h.je_batch_id
AND b.status = 'P'
AND l.je_header_id = h.je_header_id
AND h.je_category = 'Revaluation'
AND h.period_name = p1.period_name
AND p1.period_set_name = 'Equant Master'
AND p2.period_name = 'SEP-16'
AND p2.period_set_name = 'Equant Master'
AND p1.start_date <= p2.end_date
AND h.set_of_books_id = '1429'
GROUP BY cc.segment1,
cc.segment2,
h.currency_code
请建议
答案 0 :(得分:1)
我发现您正在使用Oracle电子商务套件数据模型。在该模型中,作为会计期间表(通常是数周或数月)的GL_PERIODS
通常相当小。此外,您告诉它您希望每个之前期间到2016年9月,这可能几乎是您的“Equant Master”期间设置的所有期间。根据您定义的其他期间集的数量,您的全表扫描很可能是最佳(最快运行)计划。
正如其他人正确指出的那样,全表扫描不一定比其他访问路径更差或更慢。
要确定您的FTS是否确实存在问题,您可以使用DBMS_XPLAN
来确定计划中每个步骤的时间。像这样:
alter session set statistics_level = ALL;
SELECT *
FROM TABLE (DBMS_XPLAN.display_cursor (null, null,
'ALLSTATS LAST'));
输出将告诉您完全为什么您的查询花了这么长时间(如果 花费很长时间)。它比在解释计划中选择所有全表扫描要准确得多。
答案 1 :(得分:0)
首先,您为什么要避免全表扫描?所有全表扫描都不错。
您正在加入同一个表cc.code_combination_id = l.code_combination_id。我不认为有一点可以避免对这些类型的连接进行全表扫描。
为了理解这一点,我创建了测试表和数据。
创建表I1(n号主键,v varchar2(10)); create table I2(n number primary key,v varchar2(10));
和地图表 创建表MAP(n号主键,i1号引用I1(n), i2号参考I2(n));
我在地图表上创建了索引。 在地图上创建索引map_index_i1(i1); 在地图上创建索引map_index_i2(i2);
以下是我插入的示例数据。
SQL&GT;从i1中选择*;
N V
1 ONE
2 TWO
5 FIVE
SQL&GT;从i2中选择*;
N V
3 THREE
4 FOUR
5 FIVE
SQL&GT; select * from map;
N I1 I2
1 1 3
2 1 4
5 5 5
我收集了统计数据。然后,我执行了使用映射表中的I1和I2的查询。
explain plan for
select map.n,i1.v
from i1,map
where map.i2 = map.i1
and i1.n=5
请记住,我们在地图表的I1和I2上有索引。我认为优化器可能会使用索引,但不幸的是它并没有。
因为条件map.i2 = map.i1意味着将地图表的I2列的每条记录与I1进行比较。
接下来,我在where条件中使用了一个索引列,现在它选择了索引。
explain plan for
select map.n,i1.v
from i1,map
where map.i2 = map.i1
and i1.n=5
and map.i1=5
查看ASK Tom的页面进行全表扫描。不幸的是,我不能粘贴源链接,因为我的声誉不到10!