summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaliy Filippov <[email protected]>2026-07-10 12:25:27 +0300
committerGitHub <[email protected]>2026-07-10 12:25:27 +0300
commit08e140fa0e3ed7efaa1d2edc978777216fdcadba (patch)
treeb8e98d258edbc0b44f91c0c423f976dc8ec17716
parent373ee819e1d6ae0f11d1c7c6b77ba06a84c3bfb7 (diff)
Limit the amount of stored index builds (#46024)
-rw-r--r--ydb/core/protos/schemeshard_config.proto3
-rw-r--r--ydb/core/tx/schemeshard/index/build_index__create.cpp23
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_impl.cpp2
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_impl.h1
-rw-r--r--ydb/core/tx/schemeshard/ut_helpers/test_env.cpp3
-rw-r--r--ydb/core/tx/schemeshard/ut_helpers/test_env.h1
-rw-r--r--ydb/core/tx/schemeshard/ut_index_build/ut_index_build.cpp35
7 files changed, 68 insertions, 0 deletions
diff --git a/ydb/core/protos/schemeshard_config.proto b/ydb/core/protos/schemeshard_config.proto
index e4f6537d747..f267c405dca 100644
--- a/ydb/core/protos/schemeshard_config.proto
+++ b/ydb/core/protos/schemeshard_config.proto
@@ -44,4 +44,7 @@ message TSchemeShardConfig {
// maximum allowed parallelism (PARALLEL=) for non-restore index build operations
optional uint32 MaxBuildIndexShardsInFlight = 10 [default = 1000];
+
+ // maximum recent index build operations to maintain (older ones are removed)
+ optional uint32 MaxStoredIndexBuilds = 11 [default = 1000];
}
diff --git a/ydb/core/tx/schemeshard/index/build_index__create.cpp b/ydb/core/tx/schemeshard/index/build_index__create.cpp
index 116d3ac399c..0415e8b8144 100644
--- a/ydb/core/tx/schemeshard/index/build_index__create.cpp
+++ b/ydb/core/tx/schemeshard/index/build_index__create.cpp
@@ -296,6 +296,29 @@ public:
<< ", but requested " << settings.max_shards_in_flight());
}
+ if (Self->MaxStoredIndexBuilds > 0 &&
+ Self->IndexBuilds.size() >= Self->MaxStoredIndexBuilds) {
+ // Remove oldest items from IndexBuilds
+ std::vector<std::shared_ptr<TIndexBuildInfo>> toErase;
+ for (auto& [timestamp, id]: Self->IndexBuildsByTime) {
+ auto olderBuild = Self->IndexBuilds.at(id);
+ if (olderBuild->IsFinished()) {
+ toErase.push_back(olderBuild);
+ if (Self->IndexBuilds.size() - toErase.size() < Self->MaxStoredIndexBuilds) {
+ break;
+ }
+ }
+ }
+ for (auto& olderBuild: toErase) {
+ if (!Self->PersistBuildIndexForget(db, *olderBuild)) {
+ return false;
+ }
+ }
+ for (auto& olderBuild: toErase) {
+ EraseBuildInfo(*olderBuild);
+ }
+ }
+
buildInfo->ScanSettings.CopyFrom(settings.GetScanSettings());
if (settings.max_shards_in_flight() > 0) {
buildInfo->MaxInProgressShards = settings.max_shards_in_flight();
diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.cpp b/ydb/core/tx/schemeshard/schemeshard_impl.cpp
index 3c783e4cd2a..1a9f150c939 100644
--- a/ydb/core/tx/schemeshard/schemeshard_impl.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard_impl.cpp
@@ -5730,6 +5730,7 @@ void TSchemeShard::OnActivateExecutor(const TActorContext &ctx) {
MaxCdcInitialScanShardsInFlight = appData->SchemeShardConfig.GetMaxCdcInitialScanShardsInFlight();
MaxRestoreBuildIndexShardsInFlight = appData->SchemeShardConfig.GetMaxRestoreBuildIndexShardsInFlight();
MaxBuildIndexShardsInFlight = appData->SchemeShardConfig.GetMaxBuildIndexShardsInFlight();
+ MaxStoredIndexBuilds = appData->SchemeShardConfig.GetMaxStoredIndexBuilds();
ConfigureCondErase(appData->SchemeShardConfig, ctx);
SendStatsIntervalSecondsDedicated = appData->StatisticsConfig.GetBaseStatsSendIntervalSecondsDedicated();
@@ -8655,6 +8656,7 @@ void TSchemeShard::ApplyConsoleConfigs(const NKikimrConfig::TAppConfig& appConfi
MaxCdcInitialScanShardsInFlight = schemeShardConfig.GetMaxCdcInitialScanShardsInFlight();
MaxRestoreBuildIndexShardsInFlight = schemeShardConfig.GetMaxRestoreBuildIndexShardsInFlight();
MaxBuildIndexShardsInFlight = schemeShardConfig.GetMaxBuildIndexShardsInFlight();
+ MaxStoredIndexBuilds = schemeShardConfig.GetMaxStoredIndexBuilds();
ConfigureCondErase(schemeShardConfig, ctx);
}
diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.h b/ydb/core/tx/schemeshard/schemeshard_impl.h
index 50ea19ee6d3..a8639f29ef4 100644
--- a/ydb/core/tx/schemeshard/schemeshard_impl.h
+++ b/ydb/core/tx/schemeshard/schemeshard_impl.h
@@ -444,6 +444,7 @@ public:
ui32 MaxCdcInitialScanShardsInFlight = 10;
ui32 MaxRestoreBuildIndexShardsInFlight = 0;
ui32 MaxBuildIndexShardsInFlight = 0;
+ ui32 MaxStoredIndexBuilds = 0;
TDuration StatsMaxExecuteTime;
TDuration StatsBatchTimeout;
diff --git a/ydb/core/tx/schemeshard/ut_helpers/test_env.cpp b/ydb/core/tx/schemeshard/ut_helpers/test_env.cpp
index 964ffc5e49c..c826b8891d8 100644
--- a/ydb/core/tx/schemeshard/ut_helpers/test_env.cpp
+++ b/ydb/core/tx/schemeshard/ut_helpers/test_env.cpp
@@ -701,6 +701,9 @@ NSchemeShardUT_Private::TTestEnv::TTestEnv(TTestActorRuntime& runtime, const TTe
if (opts.MaxBuildIndexShardsInFlight_) {
app.SchemeShardConfig.SetMaxBuildIndexShardsInFlight(*opts.MaxBuildIndexShardsInFlight_);
}
+ if (opts.MaxStoredIndexBuilds_) {
+ app.SchemeShardConfig.SetMaxStoredIndexBuilds(*opts.MaxStoredIndexBuilds_);
+ }
// graph settings
if (opts.GraphBackendType_) {
diff --git a/ydb/core/tx/schemeshard/ut_helpers/test_env.h b/ydb/core/tx/schemeshard/ut_helpers/test_env.h
index b669c5784cf..e68010330ae 100644
--- a/ydb/core/tx/schemeshard/ut_helpers/test_env.h
+++ b/ydb/core/tx/schemeshard/ut_helpers/test_env.h
@@ -89,6 +89,7 @@ namespace NSchemeShardUT_Private {
OPTION(std::optional<ui32>, CondEraseResponseBatchSize, std::nullopt);
OPTION(std::optional<ui32>, CondEraseResponseBatchMaxTimeMs, std::nullopt);
OPTION(std::optional<ui32>, MaxBuildIndexShardsInFlight, std::nullopt);
+ OPTION(std::optional<ui32>, MaxStoredIndexBuilds, std::nullopt);
OPTION(bool, EnableDataShardSplitHistogramSorting, false);
OPTION(bool, EnableDataShardSplitKeySelection, false);
OPTION(bool, EnableDataShardSplitHistogramOmission, false);
diff --git a/ydb/core/tx/schemeshard/ut_index_build/ut_index_build.cpp b/ydb/core/tx/schemeshard/ut_index_build/ut_index_build.cpp
index e09b9b31929..278c01ea6ab 100644
--- a/ydb/core/tx/schemeshard/ut_index_build/ut_index_build.cpp
+++ b/ydb/core/tx/schemeshard/ut_index_build/ut_index_build.cpp
@@ -1787,6 +1787,41 @@ Y_UNIT_TEST_SUITE(IndexBuildTest) {
env.TestWaitNotification(runtime, txId);
}
}
+
+ // Check that oldest builds are erased when MaxStoredIndexBuilds limit is exceeded
+ Y_UNIT_TEST(MaxStoredIndexBuilds) {
+ TTestBasicRuntime runtime;
+ TTestEnv env(runtime, TTestEnvOptions().MaxStoredIndexBuilds(2));
+ ui64 txId = 100;
+
+ TestCreateTable(runtime, ++txId, "/MyRoot", R"(
+ Name: "Table"
+ Columns { Name: "key" Type: "Uint32" }
+ Columns { Name: "index" Type: "Uint32" }
+ KeyColumnNames: ["key"]
+ )");
+ env.TestWaitNotification(runtime, txId);
+
+ TestBuildIndex(runtime, ++txId, TTestTxConfig::SchemeShard, "/MyRoot", "/MyRoot/Table",
+ TBuildIndexConfig{"index1", NKikimrSchemeOp::EIndexTypeGlobal, {"index"}, {}, {}});
+ env.TestWaitNotification(runtime, txId);
+
+ TestBuildIndex(runtime, ++txId, TTestTxConfig::SchemeShard, "/MyRoot", "/MyRoot/Table",
+ TBuildIndexConfig{"index2", NKikimrSchemeOp::EIndexTypeGlobal, {"index"}, {}, {}});
+ env.TestWaitNotification(runtime, txId);
+
+ auto listing = TestListBuildIndex(runtime, TTestTxConfig::SchemeShard, "/MyRoot");
+ UNIT_ASSERT_VALUES_EQUAL(listing.EntriesSize(), 2);
+
+ // Normal request
+ TestBuildIndex(runtime, ++txId, TTestTxConfig::SchemeShard, "/MyRoot", "/MyRoot/Table",
+ TBuildIndexConfig{"index3", NKikimrSchemeOp::EIndexTypeGlobal, {"index"}, {}, {}});
+ env.TestWaitNotification(runtime, txId);
+
+ // Check that the oldest request is forgotten
+ listing = TestListBuildIndex(runtime, TTestTxConfig::SchemeShard, "/MyRoot");
+ UNIT_ASSERT_VALUES_EQUAL(listing.EntriesSize(), 2);
+ }
}