競合/無効ヒント句の挙動

 


結果まとめ

MySQL
競合ヒント句→ 競合部分は最初のヒントが使用される。その他の部分は有効。
無効ヒント句→ 無効ヒント句よりも前に記載のヒント句は有効、後に記載のヒント句は無効。


Oracle
競合ヒント句→ 競合部分は無視される。その他の部分は有効。
無効ヒント句→ 無効ヒント句よりも前に記載のヒント句は有効、後に記載のヒント句は無効。


PostgreSQL
競合ヒント句→ 競合部分は最後のヒントが使用される。その他の部分は有効。
無効ヒント句→ 無効ヒント句よりも前に記載のヒント句は有効、後に記載のヒント句は無効。

SQL Server
競合ヒント句→ 競合部分は無視される。その他の部分は有効。
無効ヒント句→ SQL文がエラーとなる

(8.0.29)


drop table tab1 ;
drop table tab2 ;
create table tab1(col1 int,col2 int);
create table tab2(col1 int,col2 int);


drop procedure proc1;

delimiter //
create procedure proc1(in x bigint)
begin
  declare i bigint;
  set i = 0;
  start transaction;
  while i < x do
    set i = i + 1;
    insert into tab1(col1,col2) select ceil(rand()*100000), ceil(rand()*100000);
    insert into tab2(col1,col2) select ceil(rand()*100000), ceil(rand()*100000);
  end while;
  commit;
end
//
delimiter ;

call proc1(1000000);


select count(*) from tab1;
select count(*) from tab2;
select * from tab1 limit 10;
select * from tab2 limit 10;

create index ind1 on tab1(col2);
create index ind2 on tab2(col2);

 


explain analyze
select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
show warnings;


explain analyze
select /*+  NO_INDEX(t1 ind1) INDEX(t1 ind1) */ count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
show warnings;

explain analyze
select /*+ JOIN_ORDER(t2,t1) NO_INDEX(t1 ind1) INDEX(t1 ind1) */ count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
show warnings;


explain analyze
select /*+  NO_INDEX(t1 ind1) INDEX(t1 ind1) JOIN_ORDER(t1,t2) */ count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
show warnings;


競合ヒント句は最初のヒントが使用される。その他の部分は有効。


explain analyze
select /*+ JOIN_ORDER(t2,t1)  NO_INDEXXX(t1 ind1)  */ count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
show warnings;


explain analyze
select /*+   NO_INDEXXX(t1 ind1) JOIN_ORDER(t2,t1) */ count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
show warnings;

無効ヒント句よりも前に記載のヒント句は有効、後に記載のヒント句は無効。

(19c)


drop table tab1 purge;
drop table tab2 purge;
create table tab1(col1 int,col2 int);
create table tab2(col1 int,col2 int);

declare
begin
for i in 1..1000000 loop
  insert into tab1(col1,col2) values(ceil(dbms_random.value()*100000), ceil(dbms_random.value()*100000) );
  insert into tab2(col1,col2) values(ceil(dbms_random.value()*100000), ceil(dbms_random.value()*100000) );
  
end loop;
end;
/

commit;

 

select count(*) from tab1;
select count(*) from tab2;
select * from tab1 fetch first 10 rows only;
select * from tab2 fetch first 10 rows only;

create index ind1 on tab1(col2);
create index ind2 on tab2(col2);


explain plan for
select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
select * from table(dbms_xplan.display(format => 'ALL') );


explain plan for
select /*+ FULL(t1) INDEX(t1 ind1)  */  count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
select * from table(dbms_xplan.display(format => 'ALL') );


explain plan for
select /*+ LEADING(t1 t2) INDEX(t1 ind1) FULL(t1) */  count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
select * from table(dbms_xplan.display(format => 'ALL') );


explain plan for
select /*+ FULL(t1) INDEX(t1 ind1) LEADING(t2 t1)  */  count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
select * from table(dbms_xplan.display(format => 'ALL') );


競合ヒント句は無視される。その他の部分は有効。

explain plan for
select /*+ LEADING(t1 t2) INDEXXX(t1 ind1)  */  count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
select * from table(dbms_xplan.display(format => 'ALL') );

explain plan for
select /*+ INDEXXX(t1 ind1) LEADING(t2 t1)  */  count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
select * from table(dbms_xplan.display(format => 'ALL') );


無効ヒント句よりも前に記載のヒント句は有効、後に記載のヒント句は無効。

 

 

(14)


drop table tab1 ;
drop table tab2 ;
create table tab1(col1 int,col2 int);
create table tab2(col1 int,col2 int);

insert into tab1(col1,col2) select ceil(random()*100000), ceil(random()*100000) from generate_series(1,1000000);
insert into tab2(col1,col2) select ceil(random()*100000), ceil(random()*100000) from generate_series(1,1000000);

 

select count(*) from tab1;
select count(*) from tab2;
select * from tab1 limit 10;
select * from tab2 limit 10;

create index ind1 on tab1(col2);
create index ind2 on tab2(col2);


set pg_hint_plan.debug_print = 'on';
show pg_hint_plan.debug_print;

 

explain analyze
select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;


/*+ IndexScan(t1 ind1) SeqScan(t1) */
explain analyze
select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;

/*+ MergeJoin(t1 t2) SeqScan(t1) IndexScan(t1 ind1) */
explain analyze
select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;


/*+ SeqScan(t1) IndexScan(t1 ind1) MergeJoin(t1 t2) */
explain analyze
select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;


競合ヒント句は最後のヒントが使用される。その他の部分は有効。


/*+ MergeJoin(t1 t2) SeqScannnn(t1) */
explain analyze
select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;


/*+ SeqScannnn(t1) MergeJoin(t1 t2) */
explain analyze
select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;

無効ヒント句よりも前に記載のヒント句は有効、後に記載のヒント句は無効。

 

(2019)


drop table tab1 ;
drop table tab2 ;
create table tab1(col1 int,col2 int);
create table tab2(col1 int,col2 int);


set nocount on
declare @i bigint;
set @i = 1;
begin transaction;
while @i <= 1000000
begin
  insert into tab1(col1,col2) select ceiling(rand()*100000), ceiling(rand()*100000);
  insert into tab2(col1,col2) select ceiling(rand()*100000), ceiling(rand()*100000);
  set @i = @i + 1;
end
commit;

 


select count(*) from tab1;
select count(*) from tab2;
select top(10) * from tab1 ;
select top(10) * from tab2 ;

create index ind1 on tab1(col2);
create index ind2 on tab2(col2);


set showplan_all on
go

select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000
;


select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000
OPTION (  HASH JOIN , LOOP JOIN );

select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000
OPTION (  FORCE ORDER , HASH JOIN , LOOP JOIN  );


select count(*)
from tab2 t2 inner join tab1 t1
on t1.col1 = t2.col1
and t1.col2 < 1000
OPTION (HASH JOIN , LOOP JOIN , FORCE ORDER  );


競合ヒント句は無視される。その他の部分は有効。


select count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000
OPTION ( LOOOOOOP JOIN );

無効クエリヒント句はSQL文がエラーとなる