This is an automated email from the ASF dual-hosted git repository.

wyxxxcat pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 94ad13936af [improvement](cloud) Skip delete bitmap lookup for non-MoW 
rowsets (#68256)
94ad13936af is described below

commit 94ad13936afd43426e5882930a829ebb5e32618e
Author: Yixuan Wang <[email protected]>
AuthorDate: Wed Oct 28 15:04:42 2026 +0800

    [improvement](cloud) Skip delete bitmap lookup for non-MoW rowsets (#68256)
    
    ### What problem does this PR solve?
    
    Issue Number: N/A
    
    Related PR: N/A
    
    Problem Summary: Rowset recycling queried versioned delete bitmap
    metadata for non-MoW rowsets, producing an unnecessary empty range read
    per rowset.
    
    Check whether delete bitmap cleanup is needed before reading its storage
    metadata in single-rowset, batched-rowset, and tablet recycling paths.
    
    For a 5,000-rowset non-MoW workload, this avoids 5,000 bitmap metadata
    range reads.
    
    Update the recycler benchmark to seed tablet and partition metadata,
    warm the MoW cache, and include range-read requests in get counts. Add a
    unit test that checks the non-MoW skip and preserves the MoW path.
    
    ### Release note
    
    None
    
    ### Check List (For Author)
    
    - Test: Unit test added and recycler benchmark updated; passing status
    not verified.
    - Behavior changed: Yes. Non-MoW rowsets skip delete bitmap metadata
    lookup.
    - Does this need documentation: No.
---
 cloud/src/recycler/recycler.cpp        |  91 ++++++++++++++++----------
 cloud/src/recycler/recycler.h          |   2 +-
 cloud/test/recycler_benchmark_test.cpp | 115 ++++++++++++++++++++++++---------
 cloud/test/recycler_test.cpp           |  56 ++++++++++++++++
 4 files changed, 199 insertions(+), 65 deletions(-)

diff --git a/cloud/src/recycler/recycler.cpp b/cloud/src/recycler/recycler.cpp
index d5f30852600..ce9cd8f03bb 100644
--- a/cloud/src/recycler/recycler.cpp
+++ b/cloud/src/recycler/recycler.cpp
@@ -3939,19 +3939,24 @@ int InstanceRecycler::delete_rowset_data(const 
RowsetMetaCloudPB& rs_meta_pb) {
         }
     }
 
-    // Process delete bitmap - check where it's stored.
-    DeleteBitmapStorageType delete_bitmap_storage_type = 
DeleteBitmapStorageType::NOT_FOUND;
-    if (decrement_delete_bitmap_packed_file_ref_counts(tablet_id, rowset_id,
-                                                       
&delete_bitmap_storage_type) != 0) {
-        LOG_WARNING("failed to decrement delete bitmap packed file ref count")
-                .tag("instance_id", instance_id_)
-                .tag("tablet_id", tablet_id)
-                .tag("rowset_id", rowset_id);
+    int should_delete_dbm = 
may_have_versioned_delete_bitmap(rs_meta_pb.partition_id(), tablet_id);
+    if (should_delete_dbm == 1) {
+        DeleteBitmapStorageType delete_bitmap_storage_type = 
DeleteBitmapStorageType::NOT_FOUND;
+        std::vector<std::string> rowset_dbm_keys;
+        if (decrement_delete_bitmap_packed_file_ref_counts(
+                    tablet_id, rowset_id, &delete_bitmap_storage_type, 
nullptr) != 0) {
+            LOG_WARNING("failed to decrement delete bitmap packed file ref 
count")
+                    .tag("instance_id", instance_id_)
+                    .tag("tablet_id", tablet_id)
+                    .tag("rowset_id", rowset_id);
+            return -1;
+        }
+        if (delete_bitmap_storage_type == 
DeleteBitmapStorageType::STANDALONE_FILE) {
+            file_paths.push_back(delete_bitmap_path(tablet_id, rowset_id));
+        }
+    } else if (should_delete_dbm != 0) {
         return -1;
     }
-    if (delete_bitmap_storage_type == 
DeleteBitmapStorageType::STANDALONE_FILE) {
-        file_paths.push_back(delete_bitmap_path(tablet_id, rowset_id));
-    }
     // TODO(AlexYue): seems could do do batch
     return accessor->delete_files(file_paths);
 }
@@ -4198,6 +4203,7 @@ int 
InstanceRecycler::decrement_packed_file_ref_counts(const doris::RowsetMetaCl
 int InstanceRecycler::decrement_delete_bitmap_packed_file_ref_counts(
         int64_t tablet_id, const std::string& rowset_id, 
DeleteBitmapStorageType* out_storage_type,
         std::vector<std::string>* keys) {
+    
TEST_SYNC_POINT("InstanceRecycler::decrement_delete_bitmap_packed_file_ref_counts");
     if (out_storage_type) {
         *out_storage_type = DeleteBitmapStorageType::NOT_FOUND;
     }
@@ -4605,24 +4611,31 @@ int InstanceRecycler::delete_rowset_data(
             continue;
         }
 
-        DeleteBitmapStorageType delete_bitmap_storage_type = 
DeleteBitmapStorageType::NOT_FOUND;
-        std::vector<std::string> rowset_dbm_keys;
-        if (decrement_delete_bitmap_packed_file_ref_counts(
-                    tablet_id, rowset_id, &delete_bitmap_storage_type,
-                    delete_bitmap_key_groups ? &rowset_dbm_keys : nullptr) != 
0) {
-            LOG_WARNING("failed to decrement delete bitmap packed file ref 
count")
-                    .tag("instance_id", instance_id_)
-                    .tag("tablet_id", tablet_id)
-                    .tag("rowset_id", rowset_id);
+        int should_delete_dbm = 
may_have_versioned_delete_bitmap(rs.partition_id(), tablet_id);
+        if (should_delete_dbm == 1) {
+            DeleteBitmapStorageType delete_bitmap_storage_type = 
DeleteBitmapStorageType::NOT_FOUND;
+            std::vector<std::string> rowset_dbm_keys;
+            if (decrement_delete_bitmap_packed_file_ref_counts(
+                        tablet_id, rowset_id, &delete_bitmap_storage_type,
+                        delete_bitmap_key_groups ? &rowset_dbm_keys : nullptr) 
!= 0) {
+                LOG_WARNING("failed to decrement delete bitmap packed file ref 
count")
+                        .tag("instance_id", instance_id_)
+                        .tag("tablet_id", tablet_id)
+                        .tag("rowset_id", rowset_id)
+                        .tag("task_type", metrics_context.operation_type);
+                ret = -1;
+                continue;
+            }
+            if (!rowset_dbm_keys.empty() && delete_bitmap_key_groups) {
+                
delete_bitmap_key_groups->emplace_back(std::move(rowset_dbm_keys));
+            }
+            if (delete_bitmap_storage_type == 
DeleteBitmapStorageType::STANDALONE_FILE) {
+                file_paths.push_back(delete_bitmap_path(tablet_id, rowset_id));
+            }
+        } else if (should_delete_dbm != 0) {
             ret = -1;
             continue;
         }
-        if (!rowset_dbm_keys.empty() && delete_bitmap_key_groups) {
-            delete_bitmap_key_groups->emplace_back(std::move(rowset_dbm_keys));
-        }
-        if (delete_bitmap_storage_type == 
DeleteBitmapStorageType::STANDALONE_FILE) {
-            file_paths.push_back(delete_bitmap_path(tablet_id, rowset_id));
-        }
 
         // Process inverted indexes
         std::vector<std::pair<int64_t, std::string>> index_ids;
@@ -4827,8 +4840,7 @@ bool InstanceRecycler::is_tablet_recycled(int64_t 
tablet_id) {
     return recycled_tablets_.contains(tablet_id);
 }
 
-int InstanceRecycler::should_delete_versioned_delete_bitmap_kvs(int64_t 
partition_id,
-                                                                int64_t 
tablet_id) {
+int InstanceRecycler::may_have_versioned_delete_bitmap(int64_t partition_id, 
int64_t tablet_id) {
     bool is_mow = true;
     if (partition_id != -1) {
         std::lock_guard lock(partition_mow_cache_mutex);
@@ -4898,7 +4910,7 @@ int 
InstanceRecycler::should_delete_versioned_delete_bitmap_kvs(int64_t partitio
 
 int InstanceRecycler::delete_versioned_delete_bitmap_kvs(int64_t partition_id, 
int64_t tablet_id,
                                                          const std::string& 
rowset_id) {
-    int ret = should_delete_versioned_delete_bitmap_kvs(partition_id, 
tablet_id);
+    int ret = may_have_versioned_delete_bitmap(partition_id, tablet_id);
     if (ret <= 0) {
         return ret;
     }
@@ -5250,12 +5262,21 @@ int InstanceRecycler::recycle_tablet(int64_t tablet_id, 
RecyclerMetricsContext&
                     .tag("rowset_id", rs_meta.rowset_id_v2());
             return -1;
         }
-        if (decrement_delete_bitmap_packed_file_ref_counts(tablet_id, 
rs_meta.rowset_id_v2(),
-                                                           nullptr) != 0) {
-            LOG_WARNING("failed to decrement delete bitmap packed file ref 
count")
-                    .tag("instance_id", instance_id_)
-                    .tag("tablet_id", tablet_id)
-                    .tag("rowset_id", rs_meta.rowset_id_v2());
+        int should_delete_dbm = 
may_have_versioned_delete_bitmap(rs_meta.partition_id(), tablet_id);
+        if (should_delete_dbm == 1) {
+            DeleteBitmapStorageType delete_bitmap_storage_type = 
DeleteBitmapStorageType::NOT_FOUND;
+            std::vector<std::string> rowset_dbm_keys;
+            if (decrement_delete_bitmap_packed_file_ref_counts(tablet_id, 
rs_meta.rowset_id_v2(),
+                                                               
&delete_bitmap_storage_type,
+                                                               nullptr) != 0) {
+                LOG_WARNING("failed to decrement delete bitmap packed file ref 
count")
+                        .tag("instance_id", instance_id_)
+                        .tag("tablet_id", tablet_id)
+                        .tag("rowset_id", rs_meta.rowset_id_v2())
+                        .tag("task_type", metrics_context.operation_type);
+                return -1;
+            }
+        } else if (should_delete_dbm != 0) {
             return -1;
         }
         recycle_rowsets_number += 1;
diff --git a/cloud/src/recycler/recycler.h b/cloud/src/recycler/recycler.h
index 427cc419e71..46950970a76 100644
--- a/cloud/src/recycler/recycler.h
+++ b/cloud/src/recycler/recycler.h
@@ -517,7 +517,7 @@ private:
     // Return 1 if the versioned delete bitmap should be deleted,
     // Return 0 if it can be skipped,
     // negative on error.
-    int should_delete_versioned_delete_bitmap_kvs(int64_t partition_id, 
int64_t tablet_id);
+    int may_have_versioned_delete_bitmap(int64_t partition_id, int64_t 
tablet_id);
 
     int delete_versioned_delete_bitmap_kvs(int64_t partition_id, int64_t 
tablet_id,
                                            const std::string& rowset_id);
diff --git a/cloud/test/recycler_benchmark_test.cpp 
b/cloud/test/recycler_benchmark_test.cpp
index fe35c315b89..a6323efb41b 100644
--- a/cloud/test/recycler_benchmark_test.cpp
+++ b/cloud/test/recycler_benchmark_test.cpp
@@ -22,7 +22,6 @@
 #include <gtest/gtest.h>
 
 #include <algorithm>
-#include <atomic>
 #include <chrono>
 #include <cstddef>
 #include <cstdint>
@@ -119,6 +118,7 @@ constexpr int kMaxPackedRecyclePasses = 10;
 static_assert(kRowsetsPerBranch % kRowsetsPerPackedFile == 0);
 static_assert(kSeedCommitBatch % kRowsetsPerPackedFile == 0);
 constexpr int64_t kBenchmarkIndexId = 20000;
+constexpr int64_t kBenchmarkTableId = 30000;
 constexpr int32_t kBenchmarkSchemaVersion = 1;
 constexpr int64_t kBenchmarkDbId = 10000;
 
@@ -310,11 +310,33 @@ void put_benchmark_delete_bitmap(Transaction* txn, const 
std::string& instance_i
     }
 }
 
-// Seed `count` recycle rowset KVs for one branch. Every rowset gets a distinct
-// tablet_id so the per-tablet recycle batch limit never truncates the 
workload.
+void put_benchmark_tablet(Transaction* txn, const std::string& instance_id, 
int64_t partition_id,
+                          int64_t tablet_id, bool is_mow) {
+    TabletIndexPB tablet_index;
+    tablet_index.set_db_id(kBenchmarkDbId);
+    tablet_index.set_table_id(kBenchmarkTableId);
+    tablet_index.set_index_id(kBenchmarkIndexId);
+    tablet_index.set_partition_id(partition_id);
+    tablet_index.set_tablet_id(tablet_id);
+    txn->put(meta_tablet_idx_key({instance_id, tablet_id}), 
tablet_index.SerializeAsString());
+
+    doris::TabletMetaCloudPB tablet_meta;
+    tablet_meta.set_table_id(kBenchmarkTableId);
+    tablet_meta.set_partition_id(partition_id);
+    tablet_meta.set_tablet_id(tablet_id);
+    tablet_meta.set_index_id(kBenchmarkIndexId);
+    tablet_meta.set_enable_unique_key_merge_on_write(is_mow);
+    txn->put(meta_tablet_key(
+                     {instance_id, kBenchmarkTableId, kBenchmarkIndexId, 
partition_id, tablet_id}),
+             tablet_meta.SerializeAsString());
+}
+
+// Seed `count` recycle rowset KVs for one branch. Compacted rowsets share 
tablets
+// within one partition, as they do in a real tablet's version history.
 int seed_recycle_rowsets(TxnKv* txn_kv, const std::string& instance_id, 
RecycleRowsetBranch branch,
                          int64_t count, int64_t tablet_id_base, bool 
write_schema_kv = true,
                          DeleteBitmapVersion bitmap_version = 
DeleteBitmapVersion::kNone) {
+    constexpr int64_t kCompactedRowsetsPerTablet = 100;
     if (write_schema_kv && put_benchmark_schema(txn_kv, instance_id) != 0) {
         return -1;
     }
@@ -330,9 +352,18 @@ int seed_recycle_rowsets(TxnKv* txn_kv, const std::string& 
instance_id, RecycleR
                 return -1;
             }
         }
-        int64_t tablet_id = tablet_id_base + i;
+        int64_t tablet_id = tablet_id_base + (branch == 
RecycleRowsetBranch::kCompactedWithData
+                                                      ? i / 
kCompactedRowsetsPerTablet
+                                                      : i);
         std::string rowset_id = fmt::format("{:018d}", i);
         auto meta = make_rowset_meta(branch, tablet_id, rowset_id);
+        if (branch == RecycleRowsetBranch::kCompactedWithData) {
+            meta.set_partition_id(tablet_id_base);
+            if (i % kCompactedRowsetsPerTablet == 0) {
+                put_benchmark_tablet(txn.get(), instance_id, tablet_id_base, 
tablet_id,
+                                     bitmap_version != 
DeleteBitmapVersion::kNone);
+            }
+        }
         auto pb = make_recycle_rowset(branch, meta);
 
         std::string key;
@@ -393,6 +424,9 @@ void put_packed_recycle_rowsets(Transaction* txn, const 
std::string& instance_id
         const auto tablet_id = tablet_id_base + rowset_number;
         const auto rowset_id = fmt::format("{:018d}", rowset_number);
         auto meta = make_rowset_meta(RecycleRowsetBranch::kCompactedWithData, 
tablet_id, rowset_id);
+        meta.set_partition_id(tablet_id_base);
+        put_benchmark_tablet(txn, instance_id, tablet_id_base, tablet_id,
+                             bitmap_version != DeleteBitmapVersion::kNone);
         const std::pair<std::string, int64_t> files[] = {
                 {segment_path(tablet_id, rowset_id, 0), meta.data_disk_size()},
                 {inverted_index_path_v1(tablet_id, rowset_id, 0, 1, ""), 
meta.index_disk_size()}};
@@ -597,16 +631,16 @@ protected:
             }
             report += fmt::format("recycler benchmark: operation={}\n", 
operation_type);
             report += fmt::format(
-                    "  {:<{}}  {:>12}  {:>13}  {:>16}  {:>12}  {:>12}  {:>12}"
-                    "  {:>12}\n",
-                    "branch", branch_width, "total_ms", "recycled_num", 
"recycled_bytes",
-                    "get_keys", "put_keys", "del_keys", "total_keys");
+                    "  {:<{}}  {:>12}  {:>13}  {:>16}  {:>12}  {:>12}  {:>12}  
{:>12}\n", "branch",
+                    branch_width, "total_ms", "recycled_num", 
"recycled_bytes", "get", "put_keys",
+                    "del_keys", "total_keys");
             double total_elapsed_ms = 0;
             RecycleMetrics total_recycle_metrics;
             TxnKvCounts total_txn_kv_counts;
             for (const auto& [branch, result] : branches) {
                 report += fmt::format(
-                        "  {:<{}}  {:>12.2f}  {:>13}  {:>16}  {:>12}  {:>12}  
{:>12}  {:>12}\n",
+                        "  {:<{}}  {:>12.2f}  {:>13}  {:>16}  {:>12}  {:>12}  
{:>12}"
+                        "  {:>12}\n",
                         branch, branch_width, result.elapsed_ms, 
result.metrics.num,
                         result.metrics.bytes, result.txn_kv_counts.get, 
result.txn_kv_counts.put,
                         result.txn_kv_counts.del, 
result.txn_kv_counts.total());
@@ -616,7 +650,8 @@ protected:
                 total_txn_kv_counts += result.txn_kv_counts;
             }
             report += fmt::format(
-                    "  {:<{}}  {:>12.2f}  {:>13}  {:>16}  {:>12}  {:>12}  
{:>12}  {:>12}\n",
+                    "  {:<{}}  {:>12.2f}  {:>13}  {:>16}  {:>12}  {:>12}  
{:>12}"
+                    "  {:>12}\n",
                     "total", branch_width, total_elapsed_ms, 
total_recycle_metrics.num,
                     total_recycle_metrics.bytes, total_txn_kv_counts.get, 
total_txn_kv_counts.put,
                     total_txn_kv_counts.del, total_txn_kv_counts.total());
@@ -653,7 +688,8 @@ protected:
     }
 
     TxnKvCounts read_txn_kv_counts() const {
-        return {.get = g_bvar_txn_kv_get_count_normalized.get_value(),
+        return {.get = g_bvar_txn_kv_get_count_normalized.get_value() +
+                       g_bvar_txn_kv_range_get.count(),
                 .put = g_bvar_txn_kv_put.count() + 
g_bvar_txn_kv_atomic_set_ver_key.count() +
                        g_bvar_txn_kv_atomic_set_ver_value.count() +
                        g_bvar_txn_kv_atomic_add.count(),
@@ -719,6 +755,14 @@ protected:
         ASSERT_EQ(txn->commit(), TxnErrorCode::TXN_OK);
     }
 
+    void warm_partition_mow_cache(int64_t partition_id, bool is_mow) {
+        // Keep the timed run focused on the steady-state per-rowset path. The 
first lookup
+        // validates the seeded tablet index/meta and populates the partition 
cache.
+        ASSERT_EQ(recycler_->may_have_versioned_delete_bitmap(partition_id,
+                                                              /*tablet_id*/ 
partition_id),
+                  is_mow ? 1 : 0);
+    }
+
     int64_t count_recycle_rowsets() {
         std::string begin = recycle_rowset_key({kBenchmarkInstanceId, 0, ""});
         const auto end =
@@ -847,13 +891,15 @@ TEST_F(RecyclerBenchmarkTest, RecycleRowsets) {
                                        
RecycleRowsetBranch::kCompactedWithData, kRowsetsPerBranch,
                                        tablet_id_base),
                   0);
+        ASSERT_NO_FATAL_FAILURE(warm_partition_mow_cache(tablet_id_base, 
false));
         ASSERT_EQ(remove_benchmark_schema(txn_kv_.get(), 
kBenchmarkInstanceId), 0);
         ASSERT_NO_FATAL_FAILURE(measure("recycle_rowsets", 
"compacted_without_schema", "delete"));
         ASSERT_EQ(count_recycle_rowsets(), 0);
     });
 
     // Hold rowset count, schema and file sizes fixed; vary only data packing 
and
-    // bitmap version. V1 bitmap KVs survive rowset recycling, so isolate each 
case.
+    // bitmap version. Data-only cases model non-MoW tablets; bitmap cases 
model MoW.
+    // V1 bitmap KVs survive rowset recycling, so isolate each case.
     for (const auto& [bitmap_version, bitmap_name] :
          {std::pair {DeleteBitmapVersion::kNone, "data_only"},
           std::pair {DeleteBitmapVersion::kV1, "delete_bitmap_v1"},
@@ -867,6 +913,8 @@ TEST_F(RecyclerBenchmarkTest, RecycleRowsets) {
                                            
RecycleRowsetBranch::kCompactedWithData,
                                            kRowsetsPerBranch, tablet_id_base, 
true, bitmap_version),
                       0);
+            ASSERT_NO_FATAL_FAILURE(warm_partition_mow_cache(
+                    tablet_id_base, bitmap_version != 
DeleteBitmapVersion::kNone));
             ASSERT_EQ(count_recycle_rowsets(), kRowsetsPerBranch);
             ASSERT_NO_FATAL_FAILURE(measure("recycle_rowsets",
                                             
fmt::format("compacted_with_data/{}", bitmap_name),
@@ -878,6 +926,9 @@ TEST_F(RecyclerBenchmarkTest, RecycleRowsets) {
         run_benchmark(fmt::format("compacted_with_packed_data/{}", 
bitmap_name), [&] {
             ASSERT_NO_FATAL_FAILURE(seed_packed_recycle_rowsets(tablet_id_base 
+ kRowsetsPerBranch,
                                                                 
bitmap_version));
+            ASSERT_NO_FATAL_FAILURE(
+                    warm_partition_mow_cache(tablet_id_base + 
kRowsetsPerBranch,
+                                             bitmap_version != 
DeleteBitmapVersion::kNone));
 
             int64_t remaining = count_recycle_rowsets();
             ASSERT_EQ(remaining, kRowsetsPerBranch);
@@ -911,7 +962,6 @@ TEST_F(RecyclerBenchmarkTest, RecycleRowsets) {
                     check_recycled_bitmap_range(tablet_id_base + 
kRowsetsPerBranch));
         });
     }
-
     run_benchmark("compacted_empty", [&] {
         ASSERT_EQ(seed_recycle_rowsets(txn_kv_.get(), kBenchmarkInstanceId,
                                        RecycleRowsetBranch::kCompactedEmpty, 
kRowsetsPerBranch,
@@ -981,6 +1031,9 @@ TEST_F(RecyclerBenchmarkTest, RecycleRowsets) {
                           mixed_tablet_offset +
                                   
tablet_base_for(RecycleRowsetBranch::kCompactedWithData)),
                   0);
+        ASSERT_NO_FATAL_FAILURE(warm_partition_mow_cache(
+                mixed_tablet_offset + 
tablet_base_for(RecycleRowsetBranch::kCompactedWithData),
+                false));
         ASSERT_EQ(
                 seed_recycle_rowsets(txn_kv_.get(), kBenchmarkInstanceId,
                                      RecycleRowsetBranch::kCompactedEmpty, 
kRowsetsPerBranch,
@@ -993,26 +1046,30 @@ TEST_F(RecyclerBenchmarkTest, RecycleRowsets) {
         ASSERT_EQ(count_recycle_rowsets(), 0);
     });
 
-    // Recorded with 5,000 rowsets per branch. Recalibrate if the workload 
changes.
+    // Bulk branches use 5,000 rowsets. Recalibrate if the workload changes.
     static_assert(kRowsetsPerBranch == 5000);
     const std::map<std::string, TxnKvCounts> baseline_txn_kv_counts = {
-            {"compacted_empty", {.get = 5000, .put = 0, .del = 5000}},
-            // First schema cache fill reads one KV in addition to the 5,000 
rowset KVs.
-            {"compacted_with_data/data_only", {.get = 5001, .put = 0, .del = 
5000}},
-            {"compacted_with_data/delete_bitmap_v1", {.get = 5000, .put = 0, 
.del = 5000}},
-            {"compacted_with_data/delete_bitmap_v2", {.get = 10000, .put = 0, 
.del = 10000}},
-            {"compacted_with_packed_data/data_only", {.get = 12500, .put = 
5000, .del = 7500}},
+            {"compacted_empty", {.get = 5014, .put = 0, .del = 5000}},
+            // get = returned KVs + range-get requests (empty results count as 
one request).
+            // data_only: 5000 rowset KVs + 13 scan reads + 1 schema KV + 1 
schema read = 5015.
+            // v1: 5000 rowset KVs + 13 scan reads + 5000 empty bitmap reads = 
10013.
+            // v2: 5000 rowset KVs + 13 scan reads + 5000 bitmap KVs + 5000 
bitmap reads = 15013.
+            {"compacted_with_data/data_only", {.get = 5015, .put = 0, .del = 
5000}},
+            {"compacted_with_data/delete_bitmap_v1", {.get = 10013, .put = 0, 
.del = 5000}},
+            {"compacted_with_data/delete_bitmap_v2", {.get = 15013, .put = 0, 
.del = 10000}},
+            {"compacted_with_packed_data/data_only", {.get = 12526, .put = 
5000, .del = 7500}},
             {"compacted_with_packed_data/delete_bitmap_v1",
-             {.get = 12500, .put = 5000, .del = 7500}},
+             {.get = 17526, .put = 5000, .del = 7500}},
             {"compacted_with_packed_data/delete_bitmap_v2",
-             {.get = 17500, .put = 5000, .del = 12500}},
-            {"compacted_without_schema", {.get = 5000, .put = 0, .del = 5000}},
-            {"legacy_empty_resource", {.get = 5000, .put = 0, .del = 5000}},
-            {"legacy_with_resource", {.get = 10000, .put = 0, .del = 10000}},
-            {"mixed", {.get = 100000, .put = 20000, .del = 60000}},
-            {"prepare_abort", {.get = 45000, .put = 15000, .del = 15000}},
-            {"prepare_direct", {.get = 10000, .put = 0, .del = 10000}},
-            {"prepare_mark", {.get = 20000, .put = 5000, .del = 10000}},
+             {.get = 22526, .put = 5000, .del = 12500}},
+            // Missing schema is read once per rowset because the cache does 
not retain misses.
+            {"compacted_without_schema", {.get = 10013, .put = 0, .del = 
5000}},
+            {"legacy_empty_resource", {.get = 5008, .put = 0, .del = 5000}},
+            {"legacy_with_resource", {.get = 10009, .put = 0, .del = 10000}},
+            {"mixed", {.get = 100111, .put = 20000, .del = 60000}},
+            {"prepare_abort", {.get = 45030, .put = 15000, .del = 15000}},
+            {"prepare_direct", {.get = 10014, .put = 0, .del = 10000}},
+            {"prepare_mark", {.get = 20028, .put = 5000, .del = 10000}},
     };
     const auto& results = benchmark_results_["recycle_rowsets"];
     for (const auto& [branch, baseline_counts] : baseline_txn_kv_counts) {
diff --git a/cloud/test/recycler_test.cpp b/cloud/test/recycler_test.cpp
index b84c4ff09c3..1b65192150f 100644
--- a/cloud/test/recycler_test.cpp
+++ b/cloud/test/recycler_test.cpp
@@ -7519,6 +7519,62 @@ TEST(RecyclerTest, 
delete_rowset_data_without_delete_bitmap_meta) {
     EXPECT_EQ(deleted_paths[0], segment_path(rowset.tablet_id(), 
rowset.rowset_id_v2(), 0));
 }
 
+TEST(RecyclerTest, delete_rowset_data_skips_delete_bitmap_for_non_mow_table) {
+    auto txn_kv = std::make_shared<MemTxnKv>();
+    ASSERT_EQ(txn_kv->init(), 0);
+
+    constexpr std::string_view resource_id = 
"delete_rowset_data_skip_non_mow_dbm";
+    InstanceRecycler recycler(txn_kv, 
create_recycler_test_instance(std::string(resource_id)),
+                              thread_group, 
std::make_shared<TxnLazyCommitter>(txn_kv));
+    ASSERT_EQ(recycler.init(), 0);
+
+    constexpr int64_t table_id = 29901;
+    constexpr int64_t index_id = 29902;
+    constexpr int64_t non_mow_partition_id = 29903;
+    constexpr int64_t non_mow_tablet_id = 29904;
+    constexpr int64_t mow_partition_id = 29905;
+    constexpr int64_t mow_tablet_id = 29906;
+    ASSERT_EQ(create_tablet(txn_kv.get(), table_id, index_id, 
non_mow_partition_id,
+                            non_mow_tablet_id, false),
+              0);
+    ASSERT_EQ(
+            create_tablet(txn_kv.get(), table_id, index_id, mow_partition_id, 
mow_tablet_id, true),
+            0);
+
+    doris::TabletSchemaCloudPB schema;
+    schema.set_schema_version(1);
+    schema.set_inverted_index_storage_format(InvertedIndexStorageFormatPB::V1);
+
+    auto non_mow_rowset =
+            create_rowset(std::string(resource_id), non_mow_tablet_id, 
index_id, 1, schema);
+    non_mow_rowset.set_partition_id(non_mow_partition_id);
+    auto mow_rowset = create_rowset(std::string(resource_id), mow_tablet_id, 
index_id, 1, schema);
+    mow_rowset.set_partition_id(mow_partition_id);
+
+    std::atomic<int> decrement_calls {0};
+    auto* sp = SyncPoint::get_instance();
+    SyncPoint::CallbackGuard guard;
+    sp->set_call_back(
+            "InstanceRecycler::decrement_delete_bitmap_packed_file_ref_counts",
+            [&](auto&&) { ++decrement_calls; }, &guard);
+    sp->enable_processing();
+
+    RecyclerMetricsContext metrics_context;
+    std::map<std::string, doris::RowsetMetaCloudPB> rowsets;
+    rowsets.emplace(non_mow_rowset.rowset_id_v2(), non_mow_rowset);
+    ASSERT_EQ(recycler.delete_rowset_data(rowsets, 
RowsetRecyclingState::FORMAL_ROWSET,
+                                          metrics_context),
+              0);
+    EXPECT_EQ(decrement_calls.load(), 0);
+
+    rowsets.clear();
+    rowsets.emplace(mow_rowset.rowset_id_v2(), mow_rowset);
+    ASSERT_EQ(recycler.delete_rowset_data(rowsets, 
RowsetRecyclingState::FORMAL_ROWSET,
+                                          metrics_context),
+              0);
+    EXPECT_EQ(decrement_calls.load(), 1);
+}
+
 TEST(RecyclerTest, 
delete_versioned_delete_bitmap_kvs_caches_partition_mow_state) {
     auto txn_kv = std::make_shared<MemTxnKv>();
     ASSERT_EQ(txn_kv->init(), 0);


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

Reply via email to