Xianqing He created IMPALA-15541:
------------------------------------

             Summary: MT_DOP>0 HDFS scan hangs when a UNION child scan node is 
never opened due to a LIMIT
                 Key: IMPALA-15541
                 URL: https://issues.apache.org/jira/browse/IMPALA-15541
             Project: IMPALA
          Issue Type: Bug
          Components: Backend
    Affects Versions: Impala 5.0.0, Impala 4.5.3
            Reporter: Xianqing He


h3. Symptom

With MT_DOP > 0 and multiple fragment instances co-located on one backend, a 
query with
UNION ALL whose scan node children are below GROUP BY ... LIMIT can hang 
forever. One
fragment instance is blocked in ScanRangeSharedState::GetNextScanRange() 
waiting for a
scan range submission that never happens:

{code:java}
#2 impala::ConditionVariable::Wait
#3 impala::ScanRangeSharedState::GetNextScanRange 
(be/src/exec/hdfs-scan-node-base.cc)
#4 impala::HdfsScanNodeMt::GetNextScanRangeToRead 
(be/src/exec/hdfs-scan-node-mt.cc)
#5 impala::HdfsScanNodeBase::StartNextScanRange
#6 impala::HdfsScanNodeMt::GetNext
{code}

h3. Root cause

* ScanRangeSharedState::remaining_scan_range_submissions_ is initialized to the 
number
of fragment instances of the scan node. Each instance decrements it via the 
scope-exit
trigger at the end of HdfsScanNodeBase::IssueInitialScanRanges().
* UnionNode::Open() opens its children lazily: it only opens the current child
(child(child_idx_)->Open()). If a LIMIT above the union stops pulling rows in 
one
fragment instance before that instance opens the next union child, the child's
HdfsScanNodeMt is never opened. That instance therefore never calls
IssueInitialScanRanges() and never decrements the counter.
* Another fragment instance that did open the child (because it exhausted the 
earlier
union children) drains the ranges it submitted itself and then blocks in
ScanRangeSharedState::GetNextScanRange() until the counter reaches 0. The 
counter never
reaches 0, so the query hangs.

h3. Reproducer

Fragment instances must be co-located on one backend to share the scan range 
queue, so
use a single-backend cluster.

{code:sql}
create table repro0 (k int) row format delimited fields terminated by ',' 
stored as textfile;
-- one INSERT writes one file; at least 10 distinct keys
insert into repro0 values 
(0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),
(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24);
create table repro1 (k int) row format delimited fields terminated by ',' 
stored as textfile;
-- two INSERTs write two files, which forces two co-located fragment instances
insert into repro1 values (1),(2),(3);
insert into repro1 values (4),(5),(6);

set mt_dop=2;
-- hangs: one instance reaches the aggregation limit from repro0 and never 
opens the
-- repro1 scan; the other instance opens repro1 and waits forever for its 
submission
select k from (select k from repro0 union all select k from repro1) t group by 
1 limit 10;
{code}

Without the fix the query hangs (see stack above). With the fix it completes in 
~0.1s.

h3. Fix

In HdfsScanNodeMt::Close(), if initial_ranges_issued_ is false, decrement the 
shared
remaining_scan_range_submissions_ counter so that fragment instances waiting in
ScanRangeSharedState::GetNextScanRange() are released. This mirrors the 
decrement that
IssueInitialScanRanges() performs for instances that do issue their ranges.

h3. Testing

Added the end-to-end regression test
tests/custom_cluster/test_mt_dop.py::TestMtDopFlags::test_mt_dop_union_limit_scan_range_submission,
which sets up the tables above on a single-backend cluster, runs the query (with
EXEC_TIME_LIMIT_S as a safety net) and verifies the result. Verified that the 
test fails
(times out) without the fix and passes with it.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to