我使用指定的有序索引提示进行以下查询。我想知道我是否做错了,这使得它忽略了我的有序索引提示。
select /*+ ORDERED USE_NL (ptp payr) INDEX (ptp, PER_TIME_PERIODS_N50) INDEX (ppa, PAY_PAYROLL_ACTIONS_FK8) USE_NL (ppa ptp) USE_NL (ppa pcs) USE_NL (paa ppa) INDEX (prr2, PAY_RUN_RESULTS_N50) USE_NL (prr2 paa) INDEX (prr, PAY_RUN_RESULTS_N50) USE_NL (prr paa) */
papf.employee_number,
papf.full_name,
ppos.date_start
from pay_all_payrolls_f payr,
per_time_periods ptp,
pay_payroll_actions ppa,
pay_consolidation_sets pcs,
pay_assignment_actions paa,
per_all_assignments_f paaf,
per_all_people_f papf,
per_periods_of_service ppos
where payr.attribute2 = 'N' -- Non-Flexi aka Monthly
and trunc(sysdate) between payr.effective_start_date and payr.effective_end_date
and ptp.payroll_id = payr.payroll_id
and trunc(sysdate) between ptp.start_date and ptp.end_date
and ppa.time_period_id = ptp.time_period_id
and ppa.action_type = 'R'
and ppa.action_status = 'C'
and pcs.consolidation_set_id = ppa.consolidation_set_id
and pcs.consolidation_set_name = 'Main Run'
and paa.payroll_action_id = ppa.payroll_action_id
and paa.action_status = 'C'
and paaf.assignment_id = paa.assignment_id
and paaf.effective_start_date =
(
select max(paaf2.effective_start_date)
from per_all_assignments_f paaf2
where paaf2.assignment_id = paaf.assignment_id
and paaf2.effective_start_date <= ptp.end_date
)
and papf.person_id = paaf.person_id
and paaf.effective_start_date between papf.effective_start_date and papf.effective_end_date
and ppos.period_of_service_id = paaf.period_of_service_id
and not exists
(
select *
from pay_element_types_f petf,
pay_input_values_f pivf,
pay_run_result_values prrv,
pay_run_results prr
where petf.attribute1 = '401'
and trunc(sysdate) between petf.effective_start_date and petf.effective_end_date
and pivf.element_type_id = petf.element_type_id
and pivf.name = 'Pay Value'
and trunc(sysdate) between pivf.effective_start_date and pivf.effective_end_date
and prrv.input_value_id = pivf.input_value_id
and prr.run_result_id = prrv.run_result_id
and prr.assignment_action_id = paa.assignment_action_id
)
and exists
(
select *
from pay_run_results prr2
where prr2.assignment_action_id = paa.assignment_action_id
)
解释计划如下:
Plan
SELECT STATEMENT ALL_ROWSCost: 10 304 693 Bytes: 113 685 Cardinality: 583
41 NESTED LOOPS
39 NESTED LOOPS Cost: 10 278 570 Bytes: 195 Cardinality: 1
37 NESTED LOOPS Cost: 10 278 569 Bytes: 182 Cardinality: 1
34 NESTED LOOPS Cost: 10 278 566 Bytes: 128 Cardinality: 1
28 NESTED LOOPS Cost: 10 278 552 Bytes: 742 Cardinality: 7
13 NESTED LOOPS Cost: 9 961 317 Bytes: 13 947 120 Cardinality: 158 490
10 NESTED LOOPS Cost: 8 836 765 Bytes: 76 406 568 Cardinality: 1 123 626
7 NESTED LOOPS Cost: 4 635 168 Bytes: 3 927 462 339 Cardinality: 74 103 063
4 NESTED LOOPS Cost: 890 613 Bytes: 52 268 552 Cardinality: 1 866 734
2 SORT UNIQUE Cost: 10 691 Bytes: 35 938 560 Cardinality: 5 989 760
1 TABLE ACCESS FULL TABLE HR.PAY_RUN_RESULTS Cost: 10 691 Bytes: 35 938 560 Cardinality: 5 989 760
3 TABLE ACCESS FULL TABLE HR.PAY_ALL_PAYROLLS_F Cost: 4 Bytes: 176 Cardinality: 8
6 TABLE ACCESS BY INDEX ROWID TABLE HR.PER_TIME_PERIODS Cost: 2 Bytes: 1 000 Cardinality: 40
5 INDEX RANGE SCAN INDEX HR.PER_TIME_PERIODS_N50 Cost: 1 Cardinality: 40
9 TABLE ACCESS BY INDEX ROWID TABLE HR.PAY_PAYROLL_ACTIONS Cost: 2 Bytes: 15 Cardinality: 1
8 INDEX RANGE SCAN INDEX HR.PAY_PAYROLL_ACTIONS_FK8 Cost: 0 Cardinality: 1
12 TABLE ACCESS BY INDEX ROWID TABLE HR.PAY_CONSOLIDATION_SETS Cost: 1 Bytes: 20 Cardinality: 1
11 INDEX UNIQUE SCAN INDEX (UNIQUE) HR.PAY_CONSOLIDATION_SETS_PK Cost: 0 Cardinality: 1
27 TABLE ACCESS BY INDEX ROWID TABLE HR.PAY_ASSIGNMENT_ACTIONS Cost: 2 Bytes: 18 Cardinality: 1
26 INDEX UNIQUE SCAN INDEX (UNIQUE) HR.PAY_ASSIGNMENT_ACTIONS_PK Cost: 1 Cardinality: 1
25 NESTED LOOPS
23 NESTED LOOPS Cost: 88 Bytes: 83 Cardinality: 1
21 HASH JOIN Cost: 86 Bytes: 60 Cardinality: 1
19 NESTED LOOPS
17 NESTED LOOPS Cost: 68 Bytes: 3 102 Cardinality: 141
15 TABLE ACCESS BY INDEX ROWID TABLE HR.PAY_RUN_RESULTS Cost: 6 Bytes: 300 Cardinality: 25
14 INDEX RANGE SCAN INDEX HR.PAY_RUN_RESULTS_N50 Cost: 3 Cardinality: 25
16 INDEX RANGE SCAN INDEX HR.PAY_RUN_RESULT_VALUES_N50 Cost: 2 Cardinality: 6
18 TABLE ACCESS BY INDEX ROWID TABLE HR.PAY_RUN_RESULT_VALUES Cost: 3 Bytes: 60 Cardinality: 6
20 TABLE ACCESS FULL TABLE HR.PAY_INPUT_VALUES_F Cost: 17 Bytes: 152 Cardinality: 4
22 INDEX RANGE SCAN INDEX (UNIQUE) HR.PAY_ELEMENT_TYPES_F_PK Cost: 1 Cardinality: 1
24 TABLE ACCESS BY INDEX ROWID TABLE HR.PAY_ELEMENT_TYPES_F Cost: 2 Bytes: 23 Cardinality: 1
33 TABLE ACCESS BY INDEX ROWID TABLE HR.PER_ALL_ASSIGNMENTS_F Cost: 2 Bytes: 22 Cardinality: 1
32 INDEX RANGE SCAN INDEX (UNIQUE) HR.PER_ASSIGNMENTS_F_PK Cost: 1 Cardinality: 1
31 SORT AGGREGATE Bytes: 13 Cardinality: 1
30 FIRST ROW Cost: 2 Bytes: 13 Cardinality: 1
29 INDEX RANGE SCAN (MIN/MAX) INDEX (UNIQUE) HR.PER_ASSIGNMENTS_F_PK Cost: 2 Bytes: 13 Cardinality: 1
36 TABLE ACCESS BY INDEX ROWID TABLE HR.PER_ALL_PEOPLE_F Cost: 3 Bytes: 54 Cardinality: 1
35 INDEX RANGE SCAN INDEX (UNIQUE) HR.PER_PEOPLE_F_PK Cost: 1 Cardinality: 1
38 INDEX UNIQUE SCAN INDEX (UNIQUE) HR.PER_PERIODS_OF_SERVICE_PK Cost: 0 Cardinality: 1
40 TABLE ACCESS BY INDEX ROWID TABLE HR.PER_PERIODS_OF_SERVICE Cost: 1 Bytes: 13 Cardinality: 1
我希望从pay_assignment_actions表转到pay_run_results表,但是它先去那里并对其进行全表扫描;完全无视我的暗示和可怕的表现。有谁知道为什么或如何解决这个问题?
答案 0 :(得分:1)
如果该索引位于内联视图或子查询中,则需要在index hint中引用查询块名称。您可以使用自动生成的查询块名称,也可以使用qb_name
提示自行创建一个。
示例架构和数据
create table pay_assignment_actions
(
assignment_action_id number,
some_other_column number
);
create table pay_run_results
(
assignment_action_id number,
some_other_column number
);
create index PAY_RUN_RESULTS_N50 on pay_run_results(assignment_action_id);
insert into pay_assignment_actions
select level, level from dual connect by level <= 100000;
insert into pay_run_results
select level, level from dual connect by level <= 100000;
begin
dbms_stats.gather_table_stats(user, 'pay_assignment_actions');
dbms_stats.gather_table_stats(user, 'pay_run_results');
end;
/
默认计划:无索引,使用alias
格式查找查询块名称
explain plan for
select *
from pay_assignment_actions paa
where exists
(
select *
from pay_run_results prr
where prr.assignment_action_id = paa.assignment_action_id
--to stop the default plan from using an index
and some_other_column = 5
);
select * from table(dbms_xplan.display(format => 'alias -predicate'));
Plan hash value: 1799975253
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 20 | 139 (3)| 00:00:01 |
| 1 | HASH JOIN RIGHT SEMI| | 1 | 20 | 139 (3)| 00:00:01 |
| 2 | TABLE ACCESS FULL | PAY_RUN_RESULTS | 1 | 10 | 69 (2)| 00:00:01 |
| 3 | TABLE ACCESS FULL | PAY_ASSIGNMENT_ACTIONS | 100K| 976K| 69 (2)| 00:00:01 |
-----------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$5DA710D3
2 - SEL$5DA710D3 / PRR@SEL$2
3 - SEL$5DA710D3 / PAA@SEL$1
使用自动生成的查询块名称强制索引
explain plan for
select /*+ index(@SEL$2 prr) */ *
from pay_assignment_actions paa
where exists
(
select *
from pay_run_results prr
where prr.assignment_action_id = paa.assignment_action_id
--to stop the default plan from using an index
and some_other_column = 5
);
select * from table(dbms_xplan.display(format => '-predicate'));
Plan hash value: 1805560573
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 20 | 476 (1)| 00:00:01 |
| 1 | HASH JOIN RIGHT SEMI | | 1 | 20 | 476 (1)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| PAY_RUN_RESULTS | 1 | 10 | 406 (1)| 00:00:01 |
| 3 | INDEX FULL SCAN | PAY_RUN_RESULTS_N50 | 100K| | 201 (1)| 00:00:01 |
| 4 | TABLE ACCESS FULL | PAY_ASSIGNMENT_ACTIONS | 100K| 976K| 69 (2)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
使用QB_NAME制作您自己的查询区块名称
explain plan for
select /*+ index(@my_subquery prr) */ *
from pay_assignment_actions paa
where exists
(
select /*+ qb_name(my_subquery) */ *
from pay_run_results prr
where prr.assignment_action_id = paa.assignment_action_id
--to stop the default plan from using an index
and some_other_column = 5
);
select * from table(dbms_xplan.display(format => 'alias -predicate'));
Plan hash value: 1805560573
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 20 | 476 (1)| 00:00:01 |
| 1 | HASH JOIN RIGHT SEMI | | 1 | 20 | 476 (1)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| PAY_RUN_RESULTS | 1 | 10 | 406 (1)| 00:00:01 |
| 3 | INDEX FULL SCAN | PAY_RUN_RESULTS_N50 | 100K| | 201 (1)| 00:00:01 |
| 4 | TABLE ACCESS FULL | PAY_ASSIGNMENT_ACTIONS | 100K| 976K| 69 (2)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$08BA3066
2 - SEL$08BA3066 / PRR@MY_SUBQUERY
3 - SEL$08BA3066 / PRR@MY_SUBQUERY
4 - SEL$08BA3066 / PAA@SEL$1
当对象跨越查询块时USE_NL
不同查询块中的对象可以通过其完整对象别名引用,如下所示:
explain plan for
select /*+ index(@SEL$2 prr) use_nl(prr@sel$2 paa@sel$1) */ *
from pay_assignment_actions paa
where exists
(
select *
from pay_run_results prr
where prr.assignment_action_id = paa.assignment_action_id
--to stop the default plan from using an index
and some_other_column = 5
);
select * from table(dbms_xplan.display(format => '-predicate'));
Plan hash value: 2326545440
--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 20 | 476 (1)| 00:00:06 |
| 1 | NESTED LOOPS | | 1 | 20 | 476 (1)| 00:00:06 |
| 2 | SORT UNIQUE | | 1 | 10 | 406 (1)| 00:00:05 |
| 3 | TABLE ACCESS BY INDEX ROWID| PAY_RUN_RESULTS | 1 | 10 | 406 (1)| 00:00:05 |
| 4 | INDEX FULL SCAN | PAY_RUN_RESULTS_N50 | 100K| | 201 (1)| 00:00:03 |
| 5 | TABLE ACCESS FULL | PAY_ASSIGNMENT_ACTIONS | 1 | 10 | 69 (2)| 00:00:01 |
--------------------------------------------------------------------------------------------------------