EXISTS on replicated table may return wrong results
Details
| Detail name | Value |
|---|---|
| Changelog Number | 13421 |
| Type | Bug |
| Status | Resolved |
| Affected Versions | Exasol 7.0.0, Exasol 7.1.0 |
| Fix Versions | Exasol 7.1.5, Exasol 7.0.15 |
| Resolution Date | 2022-01-26 |
Background
Sometimes a replicated table T_REP is selected as the SCAN table by the join optimizer. In that case each database node operates on the complete (small) table. As a result an INNER JOIN with a non-replicated table T can be executed locally by just joining the local part of that table. The result of that local join is distributed exactly like the joined non-replicated table T. The optimizer uses this property to allow further local joins in cases where T is distributed by the columns used in another join. See https://docs.exasol.com/performance/best_practices.htm#Distribu for more details on distribution keys and local distributed joins.
Description
A query can produce wrong results if the following conditions are met:
1)
- a replicated table T_REP is selected as SCAN-table
- AND there is an EXISTS condition filtering only on columns of T_REP
- AND T_REP is joined to a distributed table T_DIST
AND
2) the execution of the query makes use of the distribution keys of T_DIST in the following ways:
- another table T_DIST2 is joined on the distribution keys
- OR there is an EXISTS with another distributed table T_DIST2 on the distribution keys
- OR there is a GROUP BY only on the distribution keys of T_DIST
In these cases the operations from 2) might return wrong results because they are executed locally.
The preconditions from 1) can be checked via PROFILING (see https://docs.exasol.com/database_concepts/profiling.htm).
EXA_USER_PROFILE_LAST_DAY will show something like this:
| PART_NAME | PART_INFO | OBJECT_SCHEMA | OBJECT_NAME |
|---|---|---|---|
| SCAN | on REPLICATED table | TEST | T_REP |
| EXISTS | GLOBAL | TEST | T_EXISTS |
| JOIN | GLOBAL | TEST | T_DIST |
Example
Preparation
drop schema if exists test cascade; create schema test; create table t_rep(i int); insert into t_rep values 1,1; create table t_exists(x int); insert into t_exists values 42; create table t_dist(i int, j int, distribute by j); insert into t_dist values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10),(11,11); create table t_dist2(j int, distribute by j); insert into t_dist2 values 1,2,3,4,5,6,7,8,9,10,11;
Testcase
The following queries might have wrong results depending on the node count of the system and selected join order.
-- GROUP BY distribution key of T_DIST select t_dist.j from t_rep join t_dist on t_rep.i=t_dist.i where not exists (select 1 from t_exists where t_rep.i=t_exists.x) group by t_dist.j; -- EXISTS on distribution key of T_DIST select t_rep.i from t_rep join t_dist on t_rep.i=t_dist.i where not exists (select 1 from t_exists where t_rep.i=t_exists.x) and exists (select 1 from t_dist2 where t_dist2.j=t_dist.j); -- JOIN on distribution key of T_DIST select t_rep.i from t_rep join t_dist on t_rep.i=t_dist.i join t_dist2 on t_dist.j=t_dist2.j where not exists (select 1 from t_exists where t_rep.i=t_exists.x);
Workaround
Enforce materialization of the distributed table using ORDER BY FALSE
select t_dist.j from t_rep join (select * from t_dist order by false) as t_dist on t_rep.i=t_dist.i where not exists (select 1 from t_exists where t_rep.i=t_exists.x) and t_dist.i is not null group by t_dist.j;
Fix
The queries return the correct result.