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 を複数指定すると構文エラーとなる