zoukankan      html  css  js  c++  java
  • Oracle外连接中驱动表过滤条件在on后且为null判断导致无法使用hash join outer

    Oracle外连接中驱动表过滤条件在on后且为null判断导致无法使用hash join outer

    前言

    偶然发现的,原因尚且不明。 

    实验数据库版本11.2.0.4.0。

    环境构造

    create table a (id number,name varchar2(20));
    create table b (id number,name varchar2(20));
    insert into a values(1,'a');
    insert into a values(2,'b');
    insert into a values(3,null);
    insert into a values(4,'d');
    insert into a values(5,null);
    insert into a values(6,'a');
    insert into b values(1,'a');
    insert into b values(2,'b');
    insert into b values(3,'c');
    insert into b values(4,null);
    insert into b values(5,null);
    insert into b values(6,'a');
    commit;
    create index idx_a_id on a(id);
    create index idx_a_name on a(name);
    create index idx_b_id on b(id);
    create index idx_b_name on b(name);
    exec dbms_stats.gather_table_stats(ownname => 'ZKM',tabname => 'A',estimate_percent => 100,method_opt => 'FOR ALL COLUMNS SIZE REPEAT',degree => 1 ,no_invalidate => false); 
    exec dbms_stats.gather_table_stats(ownname => 'ZKM',tabname => 'B',estimate_percent => 100,method_opt => 'FOR ALL COLUMNS SIZE REPEAT',degree => 1 ,no_invalidate => false);

    对照SQL组

    第一组为驱动表过滤条件在on后且不是为null判断的,如下:

    SQL 1 : select a.*,b.* from a left join b on a.name=b.name and a.name='a';
    SQL 2 : select a.*,b.* from a left join b on a.name=b.name and a.id=1;

    第二组为驱动表过滤条件在on后且为null判断的,如下:

    SQL 3 : select /*+ leading(a) use_hash(a,b) */ a.*,b.* from a left join b on a.name=b.name and a.name is null;
    SQL 4 : select /*+ leading(a) use_hash(a,b) */ a.*,b.* from a left join b on a.name=b.name and a.name is not null;
    SQL 5 : select /*+ leading(a) use_hash(b) */ a.*,b.* from a left join b on a.name=b.name and a.id is not null;
    SQL 6 : select /*+ leading(a) use_hash(b) */ a.*,b.* from a left join b on a.name=b.name and a.id is null;

    第二组为被驱动表过滤条件在on后且为null判断的,如下:

    SQL  7 : select /*+ leading(a) use_hash(a,b) */ a.*,b.* from a left join b on a.name=b.name and b.name is null;
    SQL  8 : select /*+ leading(a) use_hash(a,b) */ a.*,b.* from a left join b on a.name=b.name and b.name is not null;
    SQL  9 : select /*+ leading(a) use_hash(b) */ a.*,b.* from a left join b on a.name=b.name and b.id is not null;
    SQL 10 : select /*+ leading(a) use_hash(b) */ a.*,b.* from a left join b on a.name=b.name and b.id is null;

    说明:其中,第二组和第三组强制用hint走hash join。

    实验结果汇总

    以下为SQL 1-10 能否走hash join的汇总,具体实验自己可以去执行看看。

    SQL 1 - 10 SQL 1 SQL 2 SQL 3 SQL 4 SQL 5 SQL 6 SQL 7 SQL 8 SQL 9 SQL 10
    NL/HASH? HASH JOIN OUTER NESTED LOOPS OUTER HASH JOIN OUTER

    规律总结

    只有驱动表的过滤条件在on且判定类型为is [not] null的时候会导致执行计划无法选择hash join outer

  • 相关阅读:
    葡萄城报表介绍:数据报表的七个原则
    while(scanf("%d",&n)!=EOF)
    不容易系列之(3)—— LELE的RPG难题
    错排公式
    _​_​i​n​t​6​4​ ​与​l​o​n​g​ ​l​o​n​g​ ​i​n​t
    杭电ACM 2046 阿牛的EOF牛肉串
    C++Builder 中使用 __int64 整数的问题
    折线分平面——杭电2050
    复合梯形公式与复合辛普森公式求积分
    两套蓝桥杯热身题
  • 原文地址:https://www.cnblogs.com/PiscesCanon/p/14233173.html
Copyright © 2011-2022 走看看