github-actions[bot] commented on code in PR #68282:
URL: https://github.com/apache/doris/pull/68282#discussion_r4064954098


##########
fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java:
##########
@@ -3904,7 +3904,7 @@ public void truncateTable(String dbName, String 
tableName, PartitionNamesInfo pa
             oldPartitions = truncateTableInternal(olapTable, newPartitions,
                     truncateEntireTable, recyclePartitionParamMap, forceDrop, 
version, versionTimeMs);
             if (truncateEntireTable) {
-                
Env.getCurrentEnv().getAnalysisManager().removeTableStats(olapTable.getId());
+                
Env.getCurrentEnv().getAnalysisManager().resetTableStats(olapTable);

Review Comment:
   Cloud row-count updates can repopulate this newly retained record with rows 
that the truncate discarded. CloudGlobalTransactionMgr.afterCommitTxnResp() 
sends a tableId -> updated_row_count map into 
AnalysisManager.updateUpdatedRows(), which applies it by table id and then 
journals it, but this path has no truncate generation/tablet fence and is not 
serialized by the table write lock (non-MoW tables may not take a commit lock). 
A callback that is delayed until after this reset therefore counts pre-truncate 
rows as post-truncate rows; if apply and journaling straddle the truncate, 
followers/restarts can count them even when the master was reset afterward. 
Carry a truncate/transaction generation through the cloud event (or 
serialize/reject stale events) before retaining the record.



##########
fe/fe-core/src/main/java/org/apache/doris/statistics/analysis/TableStatsMeta.java:
##########
@@ -130,6 +137,58 @@ public TableStatsMeta(long rowCount, AnalysisInfo 
analyzedJob, TableIf table) {
         update(analyzedJob, table);
     }
 
+    /**
+     * Create a record for a table which doesn't have one yet, in the state of 
an empty table. The rows
+     * loaded into the table are accumulated by {@link 
AnalysisManager#replayUpdateRowsRecord}, so a record
+     * has to exist before the first load, otherwise these rows can never be 
turned into a row count.
+     */
+    public TableStatsMeta(OlapTable table) {
+        this.ctlId = table.getDatabase().getCatalog().getId();
+        this.ctlName = table.getDatabase().getCatalog().getName();
+        this.dbId = table.getDatabase().getId();
+        this.dbName = table.getDatabase().getFullName();
+        this.tblId = table.getId();
+        this.tblName = table.getName();
+        this.idxId = -1;
+        this.indexesRowCount = buildEmptyIndexRowCount(table);
+        this.updatedRowsBase.set(0);
+    }
+

Review Comment:
   This reset seeds every materialized index with 0, but StatsCalculator adds a 
table-wide base-index delta whenever the selected index has no BE row count. 
For an aggregate/rollup index, 100 rows loaded after TRUNCATE can collapse to 
one rollup row; until BE reports that index, the fallback here becomes 0 + 100 
and materially overestimates it. Keep the post-truncate fallback scoped to the 
base index or track per-index deltas/baselines, and add coverage for a selected 
aggregate index before its BE row-count report.



##########
fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java:
##########
@@ -6767,9 +6767,10 @@ public void replayTruncateTable(TruncateTableInfo info) 
throws MetaNotFoundExcep
             // In previous versions(before 2.1.8), there is no catalog info in 
TruncateTableInfo,
             // So if the catalog info is empty, we assume it's internal table.
             getInternalCatalog().replayTruncateTable(info);
-            if (info.isEntireTable()) {
-                
Env.getCurrentEnv().getAnalysisManager().removeTableStats(info.getTblId());
-            } else {
+            // The stats record of a wholly truncated table is reset by 
InternalCatalog.replayTruncateTable()
+            // instead of being removed, so that the rows loaded after the 
truncation are still accounted
+            // for. Only the rows removed by a partition truncation are 
accounted here.
+            if (!info.isEntireTable()) {

Review Comment:
   The truncate opcode is not mixed-version safe: this new master no longer 
journals a separate stats reset, so an older FE replaying the same 
OP_TRUNCATE_TABLE still executes its pre-change removeTableStats() branch. That 
old FE then drops subsequent OP_UPDATE_ROWS events because no record exists, 
leaving SHOW/planner fallback unknown after post-truncate loads and diverging 
on failover/restart. Preserve a compatible reset marker/journal (or gate 
serving/leadership during upgrade) and add a rolling-version replay test; the 
existing reverse-direction compatibility handling does not cover this.



-- 
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