morrySnow commented on code in PR #68648:
URL: https://github.com/apache/doris/pull/68648#discussion_r4272188925


##########
fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRewriteUtil.java:
##########
@@ -166,25 +231,46 @@ private static Set<String> 
getMtmvPartitionsByRelatedPartitions(MTMV mtmv, MTMVR
             }
             Set<String> pctPartitions = entry.getValue();
             for (String pctPartition : pctPartitions) {
-                String mvPartition = relatedToMv.get(Pair.of(tableIf, 
pctPartition));
-                if (mvPartition != null) {
-                    res.add(mvPartition);
+                Set<String> mvPartitions = relatedToMv.get(Pair.of(tableIf, 
pctPartition));
+                if (mvPartitions == null) {
+                    // A partition the query reads that no MV partition is 
mapped from -- one the partition
+                    // mapping left out, an expired base partition for 
instance -- is one the MV's rows say
+                    // nothing about. With the union rewrite on it is taken 
out of the MV plan and read from
+                    // the base table, so the MV partitions the other base 
partitions map to still answer the
+                    // query and this one is passed over. Without it the MV 
alone would answer, so no partition
+                    // is answered for at all: the MV is not a candidate for 
this query and the query is
+                    // answered from the base table.
+                    if (unionRewrite) {

Review Comment:
   [P1] This case is reachable again at head `206d9a32b4a`: the latest 
recorded-intersection check only detects a partition already read into the MV; 
it does not restore a queried PCT table missing entirely from the compensation 
mapping.
   
   Use A and B partitioned by LIST(d,k), each with 
p_kept=((2020-01-01,1),(2038-01-01,1)), and B additionally with 
p_old=((2020-01-01,2)). With a 2 YEAR sync window and positive grace, 
create/refresh an MV partitioned by a.d over:
   ```sql
   SELECT a.d, b.k, COUNT(*) AS c
   FROM A a JOIN B b ON a.d = b.d
   GROUP BY a.d, b.k
   ```
   Then query the same aggregate with `WHERE a.d = '2020-01-01' AND b.k = 2`. 
Insert one matching 2020 row in A.p_kept and B.p_old: the base result has one 
group, while the scoped MV has no b.k=2 group.
   
   The triggering plan is:
   ```text
   Aggregate(a.d, b.k, count(*))
     Filter(a.d=2020-01-01 AND b.k=2)
       Join(a.d=b.d)
         Scan(A[p_kept])
         Scan(B[p_old])
   ```
   SyncLimit drops B.p_old; Transfer's query filtering then removes B entirely, 
while A keeps the merged MV descriptor. Grace admits that written MV partition. 
`calcInvalidPartitions` only invokes `getNeedCompensatePartitions` for A, 
yielding empty compensation. The new loop does see B.p_old as uncovered, but 
B's refresh snapshot names only p_kept, so `intersection(uncovered, recorded)` 
at line 190 is empty and no base branch is added. The rewrite remains 
`Filter(b.k=2) -> Scan(MV)` and loses the committed join row.
   
   Keep the recorded-intersection check for avoiding narrowed-window 
duplicates, but independently compensate or reject an entirely unmapped queried 
PCT table. Please cover this first-refresh filtered-query case alongside the 
existing narrowed-window regression. This is a static code-path verification; I 
did not run the SQL locally.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to