问题描述
我需要表 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 (将#修改为@)