[
https://issues.apache.org/jira/browse/HIVE-30146?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Work on HIVE-30146 started by Ryu Kobayashi.
--------------------------------------------
> Wrong results for LEFT JOIN when the left input is grouped on the join keys
> and no left-side column is used above the join
> --------------------------------------------------------------------------------------------------------------------------
>
> Key: HIVE-30146
> URL: https://issues.apache.org/jira/browse/HIVE-30146
> Project: Hive
> Issue Type: Bug
> Components: CBO
> Reporter: Konstantin Bereznyakov
> Assignee: Ryu Kobayashi
> Priority: Major
>
> A LEFT JOIN returns wrong results when its left input is an aggregate grouped
> exactly on the join keys (DISTINCT, GROUP BY, or UNION) and the query above
> the join uses no column from that left input. CBO removes the left input and
> the join, and the query reads only the right table.
> {code:sql}
> create table t1 (k int);
> create table t2 (k int);
> insert into t1 values (1), (1), (2);
> insert into t2 values (1), (1), (3), (4);
> select count(*) from (select distinct k from t1) a left join t2 b on a.k =
> b.k;
> select b.k from (select distinct k from t1) a left join t2 b on a.k = b.k;
> {code}
> ||Query||Expected||Actual||
> |select count( * ) ...|3|4|
> |select b.k ...|1, 1, NULL|1, 1, 3, 4|
> The second query returns the values 3 and 4, which have no match in t1. With
> {{hive.cbo.enable=false}} both queries are correct, and the same query
> written as an INNER join is also correct (2).
> The CBO plan has no join and no scan of t1:
> {noformat}
> HiveProject(_c0=[$0])
> HiveAggregate(group=[{}], agg#0=[count()])
> HiveProject(k=[$0])
> HiveFilter(condition=[IS NOT NULL($0)])
> HiveTableScan(table=[[default, t2]], table:alias=[b])
> {noformat}
> *Cause:* two parts of {{HiveSemiJoinRule}} work together:
> * {{HiveToSemiJoinRuleSwapInputs.onMatch}} matches a join whose left input is
> an Aggregate grouped on the join keys, with no column of that input used
> above the join. It does not check the join type (the code comment says "Join
> is INNER"). {{swapInputs}} then builds the swapped join with the same join
> type, so "agg LEFT JOIN t2" becomes "t2 LEFT JOIN agg", which has different
> semantics.
> * {{HiveSemiJoinRuleBase.perform}} handles a LEFT join by keeping only the
> left input. That is correct for the original orientation (the right side is
> unique on the join keys and not referenced), but after the swap it keeps t2
> and drops the real left input.
> The swap without a join-type check was added for a Project above the join in
> HIVE-20826, and HIVE-24041 added the same swap for an Aggregate above the
> join. The LEFT handling in {{perform}} dates from HIVE-15458.
> The log shows {{HiveAggregateJoinToSemiJoinRuleSwapInputs}} firing for the
> count query and {{HiveProjectJoinToSemiJoinRuleSwapInputs}} for the
> projection query. RIGHT and FULL joins are not affected, because {{perform}}
> returns for any type other than INNER or LEFT.
> *Suggested fix:* in {{HiveToSemiJoinRuleSwapInputs.onMatch}}, return unless
> the join type is INNER.
> *Workaround:* {{hive.cbo.enable=false}}.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)