Skip to content

Commit f8885bc

Browse files
committed
Materialize indexes
1 parent 526aada commit f8885bc

30 files changed

+1022
-144
lines changed

ydb/core/backup/common/metadata.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ const std::optional<std::vector<TChangefeedMetadata>>& TMetadata::GetChangefeeds
3434
return Changefeeds;
3535
}
3636

37+
void TMetadata::AddIndex(const TIndexMetadata& index) {
38+
if (!Indexes) {
39+
Indexes.emplace();
40+
}
41+
Indexes->push_back(index);
42+
}
43+
44+
const std::optional<std::vector<TIndexMetadata>>& TMetadata::GetIndexes() const {
45+
return Indexes;
46+
}
47+
3748
void TMetadata::SetEnablePermissions(bool enablePermissions) {
3849
EnablePermissions = enablePermissions;
3950
}
@@ -75,9 +86,19 @@ TString TMetadata::Serialize() const {
7586
changefeeds.AppendValue(std::move(changefeedMap));
7687
}
7788
}
78-
// We always serialize changefeeds in order to list them explicitly during import
7989
m["changefeeds"] = changefeeds;
8090

91+
NJson::TJsonArray indexes;
92+
if (Indexes) {
93+
for (const auto& index : *Indexes) {
94+
NJson::TJsonMap indexMap;
95+
indexMap["export_prefix"] = index.ExportPrefix;
96+
indexMap["impl_table_prefix"] = index.ImplTablePrefix;
97+
indexes.AppendValue(std::move(indexMap));
98+
}
99+
}
100+
m["indexes"] = indexes;
101+
81102
return NJson::WriteJson(&m, false);
82103
}
83104

@@ -108,6 +129,17 @@ TMetadata TMetadata::Deserialize(const TString& metadata) {
108129
}
109130
}
110131

132+
if (json.Has("indexes")) {
133+
result.Indexes.emplace();
134+
const NJson::TJsonValue& indexes = json["indexes"];
135+
for (const NJson::TJsonValue& index : indexes.GetArray()) {
136+
result.AddIndex({
137+
.ExportPrefix = index["export_prefix"].GetString(),
138+
.ImplTablePrefix = index["impl_table_prefix"].GetString(),
139+
});
140+
}
141+
}
142+
111143
return result;
112144
}
113145

ydb/core/backup/common/metadata.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ struct TChangefeedMetadata {
4141
TString Name;
4242
};
4343

44+
struct TIndexMetadata {
45+
TString ExportPrefix;
46+
TString ImplTablePrefix;
47+
};
48+
4449
class TMetadata {
4550
public:
4651
TMetadata() = default;
@@ -52,9 +57,13 @@ class TMetadata {
5257
void SetVersion(ui64 version);
5358
bool HasVersion() const;
5459
ui64 GetVersion() const;
60+
5561
void AddChangefeed(const TChangefeedMetadata& changefeed);
5662
const std::optional<std::vector<TChangefeedMetadata>>& GetChangefeeds() const;
5763

64+
void AddIndex(const TIndexMetadata& index);
65+
const std::optional<std::vector<TIndexMetadata>>& GetIndexes() const;
66+
5867
void SetEnablePermissions(bool enablePermissions = true);
5968
bool HasEnablePermissions() const;
6069
bool GetEnablePermissions() const;
@@ -74,6 +83,12 @@ class TMetadata {
7483
// [...]: The export must have all changefeeds listed here
7584
std::optional<std::vector<TChangefeedMetadata>> Changefeeds;
7685

86+
// Indexes:
87+
// Undefined (previous versions): we don't know if we see the export with _materialized_ indexes or without them, so list suitable S3 files to find out all materialized indexes
88+
// []: The export has no materialized indexes
89+
// [...]: The export must have all materialized indexes listed here
90+
std::optional<std::vector<TIndexMetadata>> Indexes;
91+
7792
// EnablePermissions:
7893
// Undefined (previous versions): we don't know if we see the export with permissions or without them, so check S3 for the permissions file existence
7994
// 0: The export has no permissions

ydb/core/base/table_index.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,30 @@ TString InvalidIndexType(NKikimrSchemeOp::EIndexType indexType) {
133133
return TStringBuilder() << "Invalid index type " << static_cast<int>(indexType);
134134
}
135135

136+
std::optional<NKikimrSchemeOp::EIndexType> TryConvertIndexType(Ydb::Table::TableIndex::TypeCase type) {
137+
switch (type) {
138+
case Ydb::Table::TableIndex::TypeCase::TYPE_NOT_SET:
139+
case Ydb::Table::TableIndex::TypeCase::kGlobalIndex:
140+
return NKikimrSchemeOp::EIndexTypeGlobal;
141+
case Ydb::Table::TableIndex::TypeCase::kGlobalAsyncIndex:
142+
return NKikimrSchemeOp::EIndexTypeGlobalAsync;
143+
case Ydb::Table::TableIndex::TypeCase::kGlobalUniqueIndex:
144+
return NKikimrSchemeOp::EIndexTypeGlobalUnique;
145+
case Ydb::Table::TableIndex::TypeCase::kGlobalVectorKmeansTreeIndex:
146+
return NKikimrSchemeOp::EIndexTypeGlobalVectorKmeansTree;
147+
case Ydb::Table::TableIndex::TypeCase::kGlobalFulltextIndex:
148+
return NKikimrSchemeOp::EIndexTypeGlobalFulltext;
149+
default:
150+
return std::nullopt;
151+
}
152+
}
153+
154+
NKikimrSchemeOp::EIndexType ConvertIndexType(Ydb::Table::TableIndex::TypeCase type) {
155+
const auto result = TryConvertIndexType(type);
156+
Y_ENSURE(result);
157+
return *result;
158+
}
159+
136160
bool IsCompatibleIndex(NKikimrSchemeOp::EIndexType indexType, const TTableColumns& table, const TIndexColumns& index, TString& explain) {
137161
if (const auto* broken = IsContains(table.Keys, table.Columns)) {
138162
explain = TStringBuilder()
@@ -232,7 +256,11 @@ bool DoesIndexSupportTTL(NKikimrSchemeOp::EIndexType indexType) {
232256
}
233257
}
234258

235-
std::span<const std::string_view> GetImplTables(NKikimrSchemeOp::EIndexType indexType, std::span<const TString> indexKeys) {
259+
std::span<const std::string_view> GetImplTables(
260+
NKikimrSchemeOp::EIndexType indexType,
261+
std::span<const TString> indexKeys,
262+
std::optional<Ydb::Table::FulltextIndexSettings::Layout> layout)
263+
{
236264
switch (indexType) {
237265
case NKikimrSchemeOp::EIndexTypeGlobal:
238266
case NKikimrSchemeOp::EIndexTypeGlobalAsync:
@@ -244,6 +272,9 @@ std::span<const std::string_view> GetImplTables(NKikimrSchemeOp::EIndexType inde
244272
} else {
245273
return PrefixedGlobalKMeansTreeImplTables;
246274
}
275+
case NKikimrSchemeOp::EIndexTypeGlobalFulltext:
276+
Y_ENSURE(layout);
277+
return GetFulltextImplTables(*layout);
247278
default:
248279
Y_ENSURE(false, InvalidIndexType(indexType));
249280
}

ydb/core/base/table_index.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <util/generic/string.h>
1111
#include <util/string/builder.h>
1212

13+
#include <optional>
1314
#include <span>
1415
#include <string_view>
1516

@@ -47,8 +48,13 @@ bool DoesIndexSupportTTL(NKikimrSchemeOp::EIndexType indexType);
4748

4849
NKikimrSchemeOp::EIndexType GetIndexType(const NKikimrSchemeOp::TIndexCreationConfig& indexCreation);
4950
TString InvalidIndexType(NKikimrSchemeOp::EIndexType indexType);
51+
std::optional<NKikimrSchemeOp::EIndexType> TryConvertIndexType(Ydb::Table::TableIndex::TypeCase type);
52+
NKikimrSchemeOp::EIndexType ConvertIndexType(Ydb::Table::TableIndex::TypeCase type);
5053

51-
std::span<const std::string_view> GetImplTables(NKikimrSchemeOp::EIndexType indexType, std::span<const TString> indexKeys);
54+
std::span<const std::string_view> GetImplTables(
55+
NKikimrSchemeOp::EIndexType indexType,
56+
std::span<const TString> indexKeys,
57+
std::optional<Ydb::Table::FulltextIndexSettings::Layout> layout = std::nullopt);
5258
std::span<const std::string_view> GetFulltextImplTables(Ydb::Table::FulltextIndexSettings::Layout layout);
5359
bool IsImplTable(std::string_view tableName);
5460
bool IsBuildImplTable(std::string_view tableName);

ydb/core/protos/feature_flags.proto

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,4 +244,5 @@ message TFeatureFlags {
244244
optional bool EnableShuttingDownNodeState = 218 [default = false];
245245
optional bool EnableStreamingQueriesCounters = 219 [default = false];
246246
optional bool UseYdsTopicStorageMetering = 220 [default = false];
247-
}
247+
optional bool EnableIndexMaterialization = 221 [default = false];
248+
}

ydb/core/testlib/basics/feature_flags.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class TTestFeatureFlagsHolder {
8888
FEATURE_FLAG_SETTER(EnableTopicMessageLevelParallelism)
8989
FEATURE_FLAG_SETTER(EnableTopicAutopartitioningForReplication)
9090
FEATURE_FLAG_SETTER(EnableAccessToIndexImplTables)
91+
FEATURE_FLAG_SETTER(EnableIndexMaterialization)
9192

9293
#undef FEATURE_FLAG_SETTER
9394
};

ydb/core/tx/datashard/export_s3_uploader.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "extstorage_usage_config.h"
77

88
#include <ydb/core/base/appdata.h>
9+
#include <ydb/core/base/table_index.h>
910
#include <ydb/core/protos/flat_scheme_op.pb.h>
1011
#include <ydb/library/services/services.pb.h>
1112
#include <ydb/core/backup/common/checksum.h>
@@ -978,6 +979,36 @@ IActor* TS3Export::CreateUploader(const TActorId& dataShard, ui64 txId) const {
978979
}
979980
}
980981

982+
if (scheme) {
983+
int idx = changefeeds.size() + 1;
984+
for (const auto& index : scheme->indexes()) {
985+
const auto indexType = NTableIndex::ConvertIndexType(index.type_case());
986+
const TVector<TString> indexColumns(index.index_columns().begin(), index.index_columns().end());
987+
std::optional<Ydb::Table::FulltextIndexSettings::Layout> layout;
988+
if (indexType == NKikimrSchemeOp::EIndexTypeGlobalFulltext) {
989+
const auto& settings = index.global_fulltext_index().fulltext_settings();
990+
layout = settings.has_layout() ? settings.layout() : Ydb::Table::FulltextIndexSettings::LAYOUT_UNSPECIFIED;
991+
}
992+
993+
for (const auto& implTable : NTableIndex::GetImplTables(indexType, indexColumns, layout)) {
994+
const TString implTablePrefix = TStringBuilder() << index.name() << "/" << implTable;
995+
TString exportPrefix;
996+
if (encrypted) {
997+
std::stringstream prefix;
998+
prefix << std::setfill('0') << std::setw(3) << std::right << idx++;
999+
exportPrefix = prefix.str();
1000+
} else {
1001+
exportPrefix = implTablePrefix;
1002+
}
1003+
1004+
metadata.AddIndex(TIndexMetadata{
1005+
.ExportPrefix = exportPrefix,
1006+
.ImplTablePrefix = implTablePrefix,
1007+
});
1008+
}
1009+
}
1010+
}
1011+
9811012
auto permissions = (Task.GetEnablePermissions() && Task.GetShardNum() == 0)
9821013
? GenYdbPermissions(Task.GetTable())
9831014
: Nothing();

ydb/core/tx/schemeshard/schemeshard__init.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4457,6 +4457,7 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> {
44574457
exportInfo->EndTime = TInstant::Seconds(rowset.GetValueOrDefault<Schema::Exports::EndTime>());
44584458
exportInfo->EnableChecksums = rowset.GetValueOrDefault<Schema::Exports::EnableChecksums>(false);
44594459
exportInfo->EnablePermissions = rowset.GetValueOrDefault<Schema::Exports::EnablePermissions>(false);
4460+
exportInfo->MaterializeIndexes = rowset.GetValueOrDefault<Schema::Exports::MaterializeIndexes>(false);
44604461

44614462
if (rowset.HaveValue<Schema::Exports::ExportMetadata>()) {
44624463
exportInfo->ExportMetadata = rowset.GetValue<Schema::Exports::ExportMetadata>();
@@ -4506,6 +4507,7 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> {
45064507
item.SourcePathId.OwnerId = rowset.GetValueOrDefault<Schema::ExportItems::SourceOwnerPathId>(selfId);
45074508
item.SourcePathId.LocalPathId = rowset.GetValue<Schema::ExportItems::SourcePathId>();
45084509
item.SourcePathType = rowset.GetValue<Schema::ExportItems::SourcePathType>();
4510+
item.ParentIdx = rowset.GetValueOrDefault<Schema::ExportItems::ParentIndex>(Max<ui32>());
45094511

45104512
item.State = static_cast<TExportInfo::EState>(rowset.GetValue<Schema::ExportItems::State>());
45114513
item.WaitTxId = rowset.GetValueOrDefault<Schema::ExportItems::BackupTxId>(InvalidTxId);
@@ -4651,6 +4653,17 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> {
46514653
item.Issue = rowset.GetValueOrDefault<Schema::ImportItems::Issue>(TString());
46524654
item.SrcPrefix = rowset.GetValueOrDefault<Schema::ImportItems::SrcPrefix>(TString());
46534655
item.SrcPath = rowset.GetValueOrDefault<Schema::ImportItems::SrcPath>(TString());
4656+
4657+
item.ParentIdx = rowset.GetValueOrDefault<Schema::ImportItems::ParentIndex>(Max<ui32>());
4658+
if (item.ParentIdx != Max<ui32>()) {
4659+
Y_VERIFY_S(item.ParentIdx < importInfo->Items.size(), "Invalid item's index"
4660+
<< ": importId# " << importId
4661+
<< ", itemIdx# " << item.ParentIdx);
4662+
4663+
TImportInfo::TItem& parentItem = importInfo->Items[item.ParentIdx];
4664+
parentItem.ChildItems.push_back(itemIdx);
4665+
}
4666+
46544667
if (rowset.HaveValue<Schema::ImportItems::EncryptionIV>()) {
46554668
item.ExportItemIV = NBackup::TEncryptionIV::FromBinaryString(rowset.GetValue<Schema::ImportItems::EncryptionIV>());
46564669
}

ydb/core/tx/schemeshard/schemeshard__operation_backup_restore_common.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ class TBackupRestoreOperationBase: public TSubOperation {
578578

579579
const TString& parentPath = Transaction.GetWorkingDir();
580580
const TString name = TKind::GetTableName(Transaction);
581+
const bool internal = Transaction.HasInternal() && Transaction.GetInternal();
581582

582583
LOG_NOTICE_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD,
583584
TKind::Name() << " Propose"
@@ -618,9 +619,13 @@ class TBackupRestoreOperationBase: public TSubOperation {
618619
.NotDeleted()
619620
.IsTable()
620621
.NotAsyncReplicaTable()
621-
.NotUnderOperation()
622-
.IsCommonSensePath() //forbid alter impl index tables
623-
.CanBackupTable(); //forbid backup table with indexes
622+
.NotUnderOperation();
623+
624+
if (!internal) {
625+
checks
626+
.IsCommonSensePath() // forbid alter impl index tables
627+
.CanBackupTable(); // forbid backup table with indexes
628+
}
624629

625630
if (!checks) {
626631
result->SetError(checks.GetStatus(), checks.GetError());

ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ static std::optional<NKikimrSchemeOp::TModifyScheme> CreateIndexTask(NKikimr::NS
5252

5353
auto operation = scheme.MutableCreateTableIndex();
5454
operation->SetName(dst.LeafName());
55-
5655
operation->SetType(indexInfo->Type);
56+
operation->SetState(indexInfo->State);
5757

5858
for (const auto& keyName: indexInfo->IndexKeys) {
5959
*operation->MutableKeyColumnNames()->Add() = keyName;
@@ -269,6 +269,7 @@ bool CreateConsistentCopyTables(
269269
TStringBuilder{} << "Consistent copy table doesn't support table with index type " << indexInfo->Type)};
270270
return false;
271271
}
272+
scheme->SetInternal(tx.GetInternal());
272273
result.push_back(CreateNewTableIndex(NextPartId(nextId, result), *scheme));
273274

274275
for (const auto& [srcImplTableName, srcImplTablePathId] : srcIndexPath.Base()->GetChildren()) {

0 commit comments

Comments
 (0)