ヒント句を複数指定した場合の挙動

MySQL,Oracle,PostgreSQLともに最初に指定したヒント句が有効

 

(8.0.29)

パーサーは、SELECT, UPDATE, INSERT, REPLACE ステートメントおよび DELETE ステートメントの最初のキーワードの後にオプティマイザヒントコメントを認識します。


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(10000);


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 /*+ JOIN_ORDER(t2,t1)  */ /*+ NO_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) */ /*+ JOIN_ORDER(t2,t1)  */ count(*)
from tab1 t1 inner join tab2 t2
on t1.col1 = t2.col1
and t1.col2 < 1000;
show warnings;


→ マニュアル記載どおり、最初に指定したヒント句が有効

(19c)

ヒント構文は、文ブロックを開始するINSERT、UPDATE、DELETE、SELECTまたはMERGEのいずれかのキーワードの直後でのみ指定できます。

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..10000 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 /*+ LEADING(t2 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 /*+ 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') );


→ マニュアル記載どおり、最初に指定したヒント句が有効

(14)

指定したいヒントを、実行計画を制御したいクエリの先頭のSQLブロックコメントの中に記述します。

※途中にもヒント句を記載できる模様であるが、いろいろ制約があるため、実装は非現実的


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,10000);
insert into tab2(col1,col2) select ceil(random()*100000), ceil(random()*100000) from generate_series(1,10000);

 

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;

 

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

/*+ 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;

→ マニュアル記載どおり、最初に指定したヒント句が有効

 

(2019)


SQL構文の一部であるため、OPTION を複数指定すると構文エラーとなる