Skip to content

Commit 805752b

Browse files
ivanmorozov333ivanmorozov333
andauthored
multi layers compaction configuration (#18305)
Co-authored-by: ivanmorozov333 <imorozov333@ya.ru>
1 parent 386cc57 commit 805752b

File tree

9 files changed

+58
-18
lines changed

9 files changed

+58
-18
lines changed

ydb/core/protos/flat_scheme_op.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,11 +526,13 @@ message TCompactionLevelConstructorContainer {
526526
optional uint64 ExpectedBlobsSize = 2;
527527
optional uint64 PortionsCountAvailable = 3;
528528
optional uint64 PortionsCountLimit = 4;
529+
optional uint64 PortionsSizeLimit = 5;
529530
}
530531

531532
message TOneLayer {
532533
optional uint32 ExpectedPortionSize = 1;
533534
optional float BytesLimitFraction = 2;
535+
optional uint64 SizeLimitGuarantee = 3;
534536
}
535537

536538
oneof Implementation {

ydb/core/tx/columnshard/engines/storage/optimizer/lcbuckets/constructor/one_layer.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ TConclusionStatus TOneLayerConstructor::DoDeserializeFromJson(const NJson::TJson
88
if (!json.IsMap()) {
99
return TConclusionStatus::Fail("incorrect level description");
1010
}
11+
if (json.Has("size_limit_guarantee")) {
12+
const auto& jsonValue = json["size_limit_guarantee"];
13+
if (!jsonValue.IsUInteger()) {
14+
return TConclusionStatus::Fail("incorrect size_limit_guarantee value (have to be unsigned integer)");
15+
}
16+
SizeLimitGuarantee = jsonValue.GetUInteger();
17+
}
1118
if (json.Has("bytes_limit_fraction")) {
1219
const auto& jsonValue = json["bytes_limit_fraction"];
1320
if (!jsonValue.IsDouble()) {
@@ -38,6 +45,9 @@ bool TOneLayerConstructor::DoDeserializeFromProto(const NKikimrSchemeOp::TCompac
3845
if (proto.GetOneLayer().HasBytesLimitFraction()) {
3946
BytesLimitFraction = proto.GetOneLayer().GetBytesLimitFraction();
4047
}
48+
if (proto.GetOneLayer().HasSizeLimitGuarantee()) {
49+
SizeLimitGuarantee = proto.GetOneLayer().GetSizeLimitGuarantee();
50+
}
4151
return true;
4252
}
4353

@@ -48,13 +58,16 @@ void TOneLayerConstructor::DoSerializeToProto(NKikimrSchemeOp::TCompactionLevelC
4858
if (BytesLimitFraction) {
4959
proto.MutableOneLayer()->SetBytesLimitFraction(*BytesLimitFraction);
5060
}
61+
if (SizeLimitGuarantee) {
62+
proto.MutableOneLayer()->SetSizeLimitGuarantee(SizeLimitGuarantee);
63+
}
5164
}
5265

5366
std::shared_ptr<NStorageOptimizer::NLCBuckets::IPortionsLevel> TOneLayerConstructor::DoBuildLevel(
5467
const std::shared_ptr<IPortionsLevel>& nextLevel, const ui32 indexLevel, const std::shared_ptr<TSimplePortionsGroupInfo>& portionsInfo,
5568
const TLevelCounters& counters) const {
56-
return std::make_shared<TOneLayerPortions>(
57-
indexLevel, BytesLimitFraction.value_or(1), ExpectedPortionSize.value_or(2 << 20), nextLevel, portionsInfo, counters);
69+
return std::make_shared<TOneLayerPortions>(indexLevel, BytesLimitFraction.value_or(1), ExpectedPortionSize.value_or(2 << 20), nextLevel,
70+
portionsInfo, counters, SizeLimitGuarantee);
5871
}
5972

6073
} // namespace NKikimr::NOlap::NStorageOptimizer::NLCBuckets

ydb/core/tx/columnshard/engines/storage/optimizer/lcbuckets/constructor/one_layer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class TOneLayerConstructor: public ILevelConstructor {
1212
private:
1313
std::optional<double> BytesLimitFraction;
1414
std::optional<ui64> ExpectedPortionSize;
15+
ui64 SizeLimitGuarantee = 0;
1516

1617
virtual std::shared_ptr<IPortionsLevel> DoBuildLevel(const std::shared_ptr<IPortionsLevel>& nextLevel, const ui32 indexLevel,
1718
const std::shared_ptr<TSimplePortionsGroupInfo>& portionsInfo, const TLevelCounters& counters) const override;

ydb/core/tx/columnshard/engines/storage/optimizer/lcbuckets/constructor/zero_level.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ TConclusionStatus TZeroLevelConstructor::DoDeserializeFromJson(const NJson::TJso
4040
}
4141
PortionsCountLimit = jsonValue.GetUInteger();
4242
}
43+
if (json.Has("portions_size_limit")) {
44+
const auto& jsonValue = json["portions_size_limit"];
45+
if (!jsonValue.IsUInteger()) {
46+
return TConclusionStatus::Fail("incorrect portions_size_limit value (have to be unsigned int)");
47+
}
48+
PortionsSizeLimit = jsonValue.GetUInteger();
49+
}
4350
return TConclusionStatus::Success();
4451
}
4552

@@ -59,6 +66,9 @@ bool TZeroLevelConstructor::DoDeserializeFromProto(const NKikimrSchemeOp::TCompa
5966
if (proto.GetZeroLevel().HasPortionsCountLimit()) {
6067
PortionsCountLimit = proto.GetZeroLevel().GetPortionsCountLimit();
6168
}
69+
if (proto.GetZeroLevel().HasPortionsSizeLimit()) {
70+
PortionsSizeLimit = proto.GetZeroLevel().GetPortionsSizeLimit();
71+
}
6272
return true;
6373
}
6474

@@ -75,13 +85,16 @@ void TZeroLevelConstructor::DoSerializeToProto(NKikimrSchemeOp::TCompactionLevel
7585
if (PortionsCountLimit) {
7686
proto.MutableZeroLevel()->SetPortionsCountLimit(*PortionsCountLimit);
7787
}
88+
if (PortionsSizeLimit) {
89+
proto.MutableZeroLevel()->SetPortionsSizeLimit(*PortionsSizeLimit);
90+
}
7891
}
7992

8093
std::shared_ptr<NKikimr::NOlap::NStorageOptimizer::NLCBuckets::IPortionsLevel> TZeroLevelConstructor::DoBuildLevel(
8194
const std::shared_ptr<IPortionsLevel>& nextLevel, const ui32 indexLevel, const std::shared_ptr<TSimplePortionsGroupInfo>& /*portionsInfo*/,
8295
const TLevelCounters& counters) const {
8396
return std::make_shared<TZeroLevelPortions>(indexLevel, nextLevel, counters, PortionsLiveDuration.value_or(TDuration::Max()),
84-
ExpectedBlobsSize.value_or((ui64)1 << 20), PortionsCountAvailable.value_or(10), PortionsCountLimit);
97+
ExpectedBlobsSize.value_or((ui64)1 << 20), PortionsCountAvailable.value_or(10), PortionsCountLimit, PortionsSizeLimit);
8598
}
8699

87100
} // namespace NKikimr::NOlap::NStorageOptimizer::NLCBuckets

ydb/core/tx/columnshard/engines/storage/optimizer/lcbuckets/constructor/zero_level.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class TZeroLevelConstructor: public ILevelConstructor {
1414
std::optional<ui64> ExpectedBlobsSize;
1515
std::optional<ui64> PortionsCountAvailable;
1616
std::optional<ui64> PortionsCountLimit;
17+
std::optional<ui64> PortionsSizeLimit;
1718

1819
virtual std::shared_ptr<IPortionsLevel> DoBuildLevel(const std::shared_ptr<IPortionsLevel>& nextLevel, const ui32 indexLevel,
1920
const std::shared_ptr<TSimplePortionsGroupInfo>& portionsInfo, const TLevelCounters& counters) const override;
@@ -23,7 +24,8 @@ class TZeroLevelConstructor: public ILevelConstructor {
2324
virtual bool IsEqualToSameClass(const ILevelConstructor& item) const override {
2425
const auto& itemCast = dynamic_cast<const TZeroLevelConstructor&>(item);
2526
return PortionsLiveDuration == itemCast.PortionsLiveDuration && ExpectedBlobsSize == itemCast.ExpectedBlobsSize &&
26-
PortionsCountAvailable == itemCast.PortionsCountAvailable && PortionsCountLimit == itemCast.PortionsCountLimit;
27+
PortionsCountAvailable == itemCast.PortionsCountAvailable && PortionsCountLimit == itemCast.PortionsCountLimit &&
28+
PortionsSizeLimit == itemCast.PortionsSizeLimit;
2729
}
2830

2931
static const inline TFactory::TRegistrator<TZeroLevelConstructor> Registrator =

ydb/core/tx/columnshard/engines/storage/optimizer/lcbuckets/planner/common_level.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ class TOneLayerPortions: public IPortionsLevel {
1212
const TLevelCounters LevelCounters;
1313
const double BytesLimitFraction = 1;
1414
const ui64 ExpectedPortionSize = (1 << 20);
15+
const ui64 SizeLimitGuarantee = 0;
1516
const bool StrictOneLayer = true;
1617
std::shared_ptr<TSimplePortionsGroupInfo> SummaryPortionsInfo;
1718

1819
ui64 GetLevelBlobBytesLimit() const {
19-
const ui32 discrete = SummaryPortionsInfo->GetBlobBytes() / (150 << 20);
20-
return (discrete + 1) * (150 << 20) * BytesLimitFraction;
20+
return std::max<ui64>(SizeLimitGuarantee, SummaryPortionsInfo->GetBlobBytes() * BytesLimitFraction);
2121
}
2222

2323
virtual NJson::TJsonValue DoSerializeToJson() const override {
@@ -26,6 +26,7 @@ class TOneLayerPortions: public IPortionsLevel {
2626
result.InsertValue("bytes_limit", GetLevelBlobBytesLimit());
2727
result.InsertValue("total_bytes", SummaryPortionsInfo->GetBlobBytes());
2828
result.InsertValue("fraction", BytesLimitFraction);
29+
result.InsertValue("size_limit_guarantee", SizeLimitGuarantee);
2930
return result;
3031
}
3132

@@ -74,11 +75,12 @@ class TOneLayerPortions: public IPortionsLevel {
7475
public:
7576
TOneLayerPortions(const ui64 levelId, const double bytesLimitFraction, const ui64 expectedPortionSize,
7677
const std::shared_ptr<IPortionsLevel>& nextLevel, const std::shared_ptr<TSimplePortionsGroupInfo>& summaryPortionsInfo,
77-
const TLevelCounters& levelCounters, const bool strictOneLayer = true)
78+
const TLevelCounters& levelCounters, const ui64 sizeLimitGuarantee, const bool strictOneLayer = true)
7879
: TBase(levelId, nextLevel)
7980
, LevelCounters(levelCounters)
8081
, BytesLimitFraction(bytesLimitFraction)
8182
, ExpectedPortionSize(expectedPortionSize)
83+
, SizeLimitGuarantee(sizeLimitGuarantee)
8284
, StrictOneLayer(strictOneLayer)
8385
, SummaryPortionsInfo(summaryPortionsInfo)
8486
{

ydb/core/tx/columnshard/engines/storage/optimizer/lcbuckets/planner/optimizer.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@ TOptimizerPlanner::TOptimizerPlanner(const TInternalPathId pathId, const std::sh
3131
}
3232
} else {
3333
Levels.emplace_back(std::make_shared<TZeroLevelPortions>(
34-
2, nullptr, Counters->GetLevelCounters(2), TDuration::Max(), 1 << 20, 10, std::nullopt));
34+
2, nullptr, Counters->GetLevelCounters(2), TDuration::Max(), 1 << 20, 10, std::nullopt, std::nullopt));
35+
Levels.emplace_back(
36+
std::make_shared<TZeroLevelPortions>(
37+
1, Levels.back(), Counters->GetLevelCounters(1), TDuration::Max(), 1 << 20, 10, std::nullopt, std::nullopt));
3538
Levels.emplace_back(std::make_shared<TZeroLevelPortions>(
36-
1, Levels.back(), Counters->GetLevelCounters(1), TDuration::Max(), 1 << 20, 10, std::nullopt));
37-
Levels.emplace_back(std::make_shared<TZeroLevelPortions>(
38-
0, Levels.back(), Counters->GetLevelCounters(0), TDuration::Seconds(180), 1 << 20, 10, std::nullopt));
39+
0, Levels.back(), Counters->GetLevelCounters(0), TDuration::Seconds(180), 1 << 20, 10, std::nullopt, std::nullopt));
3940
}
4041
std::reverse(Levels.begin(), Levels.end());
4142
RefreshWeights();

ydb/core/tx/columnshard/engines/storage/optimizer/lcbuckets/planner/zero_level.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ TCompactionTaskData TZeroLevelPortions::DoGetOptimizationTask() const {
99
result.AddCurrentLevelPortion(
1010
i.GetPortion(), NextLevel->GetAffectedPortions(i.GetPortion()->IndexKeyStart(), i.GetPortion()->IndexKeyEnd()), true);
1111
if (!result.CanTakeMore()) {
12-
// result.SetStopSeparation(i.GetPortion()->IndexKeyStart());
12+
// result.SetStopSeparation(i.GetPortion()->IndexKeyStart());
1313
break;
1414
}
1515
}
@@ -70,13 +70,14 @@ TInstant TZeroLevelPortions::DoGetWeightExpirationInstant() const {
7070

7171
TZeroLevelPortions::TZeroLevelPortions(const ui32 levelIdx, const std::shared_ptr<IPortionsLevel>& nextLevel,
7272
const TLevelCounters& levelCounters, const TDuration durationToDrop, const ui64 expectedBlobsSize, const ui64 portionsCountAvailable,
73-
const std::optional<ui64> portionsCountLimit)
73+
const std::optional<ui64> portionsCountLimit, const std::optional<ui64> portionsSizeLimit)
7474
: TBase(levelIdx, nextLevel)
7575
, LevelCounters(levelCounters)
7676
, DurationToDrop(durationToDrop)
7777
, ExpectedBlobsSize(expectedBlobsSize)
7878
, PortionsCountAvailable(portionsCountAvailable)
79-
, PortionsCountLimit(portionsCountLimit) {
79+
, PortionsCountLimit(portionsCountLimit)
80+
, PortionsSizeLimit(portionsSizeLimit) {
8081
if (DurationToDrop != TDuration::Max() && PredOptimization) {
8182
*PredOptimization -= TDuration::Seconds(RandomNumber<ui32>(DurationToDrop.Seconds()));
8283
}

ydb/core/tx/columnshard/engines/storage/optimizer/lcbuckets/planner/zero_level.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class TZeroLevelPortions: public IPortionsLevel {
1212
const ui64 ExpectedBlobsSize;
1313
const ui64 PortionsCountAvailable;
1414
const std::optional<ui64> PortionsCountLimit;
15+
const std::optional<ui64> PortionsSizeLimit;
1516
class TOrderedPortion {
1617
private:
1718
YDB_READONLY_DEF(TPortionInfo::TConstPtr, Portion);
@@ -41,10 +42,13 @@ class TZeroLevelPortions: public IPortionsLevel {
4142
std::set<TOrderedPortion> Portions;
4243

4344
virtual bool IsOverloaded() const override {
44-
if (!PortionsCountLimit) {
45-
return false;
45+
if (PortionsCountLimit && Portions.size() > *PortionsCountLimit) {
46+
return true;
4647
}
47-
return Portions.size() > *PortionsCountLimit;
48+
if (PortionsSizeLimit && (ui64)PortionsInfo.GetBlobBytes() > (ui64)*PortionsSizeLimit) {
49+
return true;
50+
}
51+
return false;
4852
}
4953

5054
virtual NArrow::NMerger::TIntervalPositions DoGetBucketPositions(const std::shared_ptr<arrow::Schema>& /*pkSchema*/) const override {
@@ -103,7 +107,8 @@ class TZeroLevelPortions: public IPortionsLevel {
103107

104108
public:
105109
TZeroLevelPortions(const ui32 levelIdx, const std::shared_ptr<IPortionsLevel>& nextLevel, const TLevelCounters& levelCounters,
106-
const TDuration durationToDrop, const ui64 expectedBlobsSize, const ui64 portionsCountAvailable, const std::optional<ui64> portionsCountLimit);
110+
const TDuration durationToDrop, const ui64 expectedBlobsSize, const ui64 portionsCountAvailable,
111+
const std::optional<ui64> portionsCountLimit, const std::optional<ui64> portionsSizeLimit);
107112
};
108113

109114
} // namespace NKikimr::NOlap::NStorageOptimizer::NLCBuckets

0 commit comments

Comments
 (0)