Вярвам, че това може да има нещо общо със съществуващите индекси в колоните, които използвате в OR
предикат.
Тествах със следното в 11gR2.
create table scott.test as
select level l,
decode(mod(level,2), 1, 1, 2) x,
decode(mod(level,2), 1, 2, 1) y,
dbms_random.value(1, 3) z from dual
connect by level < 1000;
/
begin
dbms_stats.gather_table_stats('scott', 'test');
end;
/
След това обясних следните заявки в TOAD, (EXPLAIN PLAN FOR
)
select x, y, z from scott.test
where (floor(z) = 1 and x = 1) or (floor(z) = 2 and y = 1)
;
SELECT STATEMENT Optimizer Mode=ALL_ROWS 10 4
TABLE ACCESS FULL COS_DM.TEST 10 280 4
select /*+ USE_CONCAT */ x, y, z from scott.test
where (floor(z) = 1 and x = 1) or (floor(z) = 2 and y = 1)
;
SELECT STATEMENT Optimizer Mode=ALL_ROWS 10 4
TABLE ACCESS FULL COS_DM.TEST 10 280 4
select x, y, z from test where (floor(z) = 1 and x = 1)
union all
select x, y, z from test where (floor(z) = 2 and y = 1)
;
SELECT STATEMENT Optimizer Mode=ALL_ROWS 10 8
UNION-ALL
TABLE ACCESS FULL COS_DM.TEST 5 140 4
TABLE ACCESS FULL COS_DM.TEST 5 140 4
Така че изглежда, че подсказката не работи. След това добавих индекс към колоните x &y:
create index test_x on test (x, y);
begin
dbms_stats.gather_table_stats('scott', 'test');
end;
/
Повторно изпълнение на заявките сега:
select x, y, z from scott.test
where (floor(z) = 1 and x = 1) or (floor(z) = 2 and y = 1)
;
SELECT STATEMENT Optimizer Mode=ALL_ROWS 10 4
TABLE ACCESS FULL COS_DM.TEST 10 280 4
select /*+ USE_CONCAT */ x, y, z from scott.test
where (floor(z) = 1 and x = 1) or (floor(z) = 2 and y = 1)
;
SELECT STATEMENT Optimizer Mode=ALL_ROWS 10 8
CONCATENATION
TABLE ACCESS FULL COS_DM.TEST 5 140 4
TABLE ACCESS FULL COS_DM.TEST 5 140 4
select x, y, z from test where (floor(z) = 1 and x = 1)
union all
select x, y, z from test where (floor(z) = 2 and y = 1)
;
SELECT STATEMENT Optimizer Mode=ALL_ROWS 10 8
UNION-ALL
TABLE ACCESS FULL COS_DM.TEST 5 140 4
TABLE ACCESS FULL COS_DM.TEST 5 140 4
Изглежда, че след добавяне на индекса (въпреки че той не се използва ) оптимизаторът все пак реши да използва подсказката!
Може би бихте могли да опитате това?