联合查询 - 强制每个查询的哈希唯一

问题描述

我需要表 T1 和 T2 中 group_name 的唯一值列表。两个表都已分区并包含数亿条记录。我感兴趣的列有一个带有最新统计数据的本地位图索引。此列大约有 500 个唯一值。 (见测试用例)。

鉴于此信息,查找唯一值的最有效方法似乎是:从 T1 中查找 500 个左右的唯一值,然后从 T2 中查找 500 个左右的唯一值,然后对列表进行重复数据删除。所以这转化为这个查询

select distinct group_name from t1 union
select distinct group_name from t2;

然而,Oracle 生成的实际执行是这样的:

SELECT
  SORT UNIQUE                <--           500 records
    UNION-ALL                <-- 1,430,000,000 records
      BITMAP INDEX FFS T1    <-- 1,300,000 records
      BITMAP INDEX FFS T2    <--   130,000 records

因此优化器似乎已将查询重新编写为类似于以下查询内容,从而有效地跳过了中间步骤中的唯一操作:

select distinct group_name
  from (select group_name from t1 union all -- No Unique here
        select group_name from t2)

这是我的实际问题: 在不重新编写查询的情况下,我可以仅使用提示来强制执行以下执行计划吗?即我的原始查询的实际编写方式?

SELECT
  SORT UNIQUE                 <--           500 
    UNION-ALL                 <--          1000
      HASH UNIQUE             <--           500 <-- Reduce early
        BITMAP INDEX FFS T1   <-- 1,000
      HASH UNIQUE             <--           500 <-- Reduce early
        BITMAP INDEX FFS T2   <--   130,000

这是一个创建上面两个表的测试用例。

create table t1(id number,group_name number,payload varchar2(100)) nologging partition by hash(id) partitions 4;
create table t2(id number,payload varchar2(100)) nologging partition by hash(id) partitions 4;

insert /*+ append */ all
  into t1
  into t2
select rownum              as id,mod(rownum,500)    as group_name,lpad('x',100,'x') as payload
  from dual connect by level <= 1e6;
      
create bitmap index t1_bx on t1(group_name) nologging local; 
create bitmap index t2_bx on t2(group_name) nologging local;

我使用的是 Oracle Database 12c 企业版 12.1.0.2.0 版 - 64 位生产

编辑: 顺便说一句,在准备测试用例时,我找到了两种解决问题的方法,但我仍然想知道是否有办法/*+ hint */解决问题。

select group_name from t1 group by group_name union
select group_name from t2 group by group_name;

with v1 as(select /*+ materialize */distinct group_name from t1),v2 as(select /*+ materialize */distinct group_name from t2)
select group_name from v1 union
select group_name from v2;

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)