@@ -764,7 +764,6 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
764
764
buildInfo.Sample .Rows , buildInfo.KMeans .Parent , buildInfo.KMeans .Child );
765
765
766
766
TActivationContext::AsActorContext ().MakeFor (Self->SelfId ()).Register (actor);
767
- buildInfo.Sample .State = TIndexBuildInfo::TSample::EState::Upload;
768
767
769
768
LOG_N (" TTxBuildProgress: TUploadSampleK: " << buildInfo);
770
769
}
@@ -807,6 +806,10 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
807
806
}
808
807
}
809
808
809
+ bool NoShardsAdded (TIndexBuildInfo& buildInfo) {
810
+ return buildInfo.DoneShards .empty () && buildInfo.InProgressShards .empty () && buildInfo.ToUploadShards .empty ();
811
+ }
812
+
810
813
void AddAllShards (TIndexBuildInfo& buildInfo) {
811
814
ToTabletSend.clear ();
812
815
Self->IndexBuildPipes .CloseAll (BuildId, Self->ActorContext ());
@@ -816,10 +819,37 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
816
819
}
817
820
}
818
821
822
+ void AddGlobalShardsForCurrentParent (TIndexBuildInfo& buildInfo) {
823
+ Y_ENSURE (NoShardsAdded (buildInfo));
824
+ if (buildInfo.KMeans .Parent == 0 ) {
825
+ AddAllShards (buildInfo);
826
+ return ;
827
+ }
828
+ auto it = buildInfo.Cluster2Shards .lower_bound (buildInfo.KMeans .Parent );
829
+ Y_ENSURE (it != buildInfo.Cluster2Shards .end ());
830
+ if (it->second .Shards .size () > 1 ) {
831
+ for (const auto & idx : it->second .Shards ) {
832
+ const auto & status = buildInfo.Shards .at (idx);
833
+ AddShard (buildInfo, idx, status);
834
+ }
835
+ }
836
+ }
837
+
838
+ void AddLocalClusters (TIndexBuildInfo& buildInfo) {
839
+ Y_ENSURE (NoShardsAdded (buildInfo));
840
+ for (const auto & [to, state] : buildInfo.Cluster2Shards ) {
841
+ if (state.Shards .size () == 1 ) {
842
+ const auto * status = buildInfo.Shards .FindPtr (state.Shards [0 ]);
843
+ Y_ENSURE (status);
844
+ AddShard (buildInfo, state.Shards [0 ], *status);
845
+ }
846
+ }
847
+ }
848
+
819
849
bool FillSecondaryIndex (TIndexBuildInfo& buildInfo) {
820
850
LOG_D (" FillSecondaryIndex Start" );
821
851
822
- if (buildInfo. DoneShards . empty () && buildInfo. ToUploadShards . empty () && buildInfo. InProgressShards . empty ( )) {
852
+ if (NoShardsAdded ( buildInfo)) {
823
853
AddAllShards (buildInfo);
824
854
}
825
855
auto done = SendToShards (buildInfo, [&](TShardIdx shardIdx) { SendBuildSecondaryIndexRequest (shardIdx, buildInfo); }) &&
@@ -833,65 +863,21 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
833
863
}
834
864
835
865
bool FillPrefixKMeans (TIndexBuildInfo& buildInfo) {
836
- if (buildInfo. DoneShards . empty () && buildInfo. ToUploadShards . empty () && buildInfo. InProgressShards . empty ( )) {
866
+ if (NoShardsAdded ( buildInfo)) {
837
867
AddAllShards (buildInfo);
838
868
}
839
869
return SendToShards (buildInfo, [&](TShardIdx shardIdx) { SendPrefixKMeansRequest (shardIdx, buildInfo); }) &&
840
870
buildInfo.DoneShards .size () == buildInfo.Shards .size ();
841
871
}
842
872
843
873
bool FillLocalKMeans (TIndexBuildInfo& buildInfo) {
844
- if (buildInfo. DoneShards . empty () && buildInfo. ToUploadShards . empty () && buildInfo. InProgressShards . empty ( )) {
874
+ if (NoShardsAdded ( buildInfo)) {
845
875
AddAllShards (buildInfo);
846
876
}
847
877
return SendToShards (buildInfo, [&](TShardIdx shardIdx) { SendKMeansLocalRequest (shardIdx, buildInfo); }) &&
848
878
buildInfo.DoneShards .size () == buildInfo.Shards .size ();
849
879
}
850
880
851
- bool InitSingleKMeans (TIndexBuildInfo& buildInfo) {
852
- if (!buildInfo.DoneShards .empty () || !buildInfo.InProgressShards .empty () || !buildInfo.ToUploadShards .empty ()) {
853
- return false ;
854
- }
855
- if (buildInfo.KMeans .State == TIndexBuildInfo::TKMeans::MultiLocal) {
856
- InitMultiKMeans (buildInfo);
857
- return false ;
858
- }
859
- if (buildInfo.KMeans .Parent == 0 ) {
860
- AddAllShards (buildInfo);
861
- } else {
862
- auto it = buildInfo.Cluster2Shards .lower_bound (buildInfo.KMeans .Parent );
863
- Y_ENSURE (it != buildInfo.Cluster2Shards .end ());
864
- if (it->second .Local == InvalidShardIdx) {
865
- for (const auto & idx : it->second .Global ) {
866
- const auto & status = buildInfo.Shards .at (idx);
867
- AddShard (buildInfo, idx, status);
868
- }
869
- }
870
- }
871
- if (buildInfo.DoneShards .size () + buildInfo.ToUploadShards .size () <= 1 ) {
872
- buildInfo.KMeans .State = TIndexBuildInfo::TKMeans::Local;
873
- }
874
- return true ;
875
- }
876
-
877
- bool InitMultiKMeans (TIndexBuildInfo& buildInfo) {
878
- if (buildInfo.Cluster2Shards .empty ()) {
879
- return false ;
880
- }
881
- Y_ENSURE (buildInfo.KMeans .Parent != 0 );
882
- for (const auto & [to, state] : buildInfo.Cluster2Shards ) {
883
- if (const auto & [from, local, global] = state; local != InvalidShardIdx) {
884
- if (const auto * status = buildInfo.Shards .FindPtr (local)) {
885
- AddShard (buildInfo, local, *status);
886
- }
887
- }
888
- }
889
- buildInfo.KMeans .State = TIndexBuildInfo::TKMeans::MultiLocal;
890
- buildInfo.Cluster2Shards .clear ();
891
- Y_ENSURE (buildInfo.InProgressShards .empty ());
892
- return !buildInfo.ToUploadShards .empty ();
893
- }
894
-
895
881
bool SendKMeansSample (TIndexBuildInfo& buildInfo) {
896
882
if (buildInfo.Sample .MaxProbability == 0 ) {
897
883
buildInfo.ToUploadShards .clear ();
@@ -910,22 +896,6 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
910
896
return SendToShards (buildInfo, [&](TShardIdx shardIdx) { SendKMeansLocalRequest (shardIdx, buildInfo); });
911
897
}
912
898
913
- bool SendVectorIndex (TIndexBuildInfo& buildInfo) {
914
- switch (buildInfo.KMeans .State ) {
915
- case TIndexBuildInfo::TKMeans::Sample:
916
- return SendKMeansSample (buildInfo);
917
- // TODO(mbkkt)
918
- // case TIndexBuildInfo::TKMeans::Recompute:
919
- // return SendKMeansRecompute(buildInfo);
920
- case TIndexBuildInfo::TKMeans::Reshuffle:
921
- return SendKMeansReshuffle (buildInfo);
922
- case TIndexBuildInfo::TKMeans::Local:
923
- case TIndexBuildInfo::TKMeans::MultiLocal:
924
- return SendKMeansLocal (buildInfo);
925
- }
926
- return true ;
927
- }
928
-
929
899
void ClearDoneShards (TTransactionContext& txc, TIndexBuildInfo& buildInfo) {
930
900
if (buildInfo.DoneShards .empty ()) {
931
901
return ;
@@ -966,6 +936,7 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
966
936
// it's approximate but upper bound, so it's ok
967
937
buildInfo.KMeans .TableSize = std::max<ui64>(1 , buildInfo.Processed .GetUploadRows ());
968
938
buildInfo.KMeans .PrefixIndexDone (doneShards);
939
+ buildInfo.KMeans .State = TIndexBuildInfo::TKMeans::MultiLocal;
969
940
LOG_D (" FillPrefixedVectorIndex PrefixIndexDone " << buildInfo.DebugString ());
970
941
971
942
PersistKMeansState (txc, buildInfo);
@@ -1006,60 +977,93 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
1006
977
}
1007
978
1008
979
bool FillVectorIndex (TTransactionContext& txc, TIndexBuildInfo& buildInfo) {
1009
- // FIXME: Very non-intuitive state machine, rework it by adding an explicit vector index fill state
1010
980
LOG_D (" FillVectorIndex Start " << buildInfo.DebugString ());
1011
981
1012
- if (buildInfo.Sample .State == TIndexBuildInfo::TSample::EState::Upload) {
1013
- return false ;
1014
- }
1015
- if (InitSingleKMeans (buildInfo)) {
1016
- LOG_D (" FillVectorIndex SingleKMeans " << buildInfo.DebugString ());
1017
- }
1018
- if (!SendVectorIndex (buildInfo)) {
1019
- return false ;
1020
- }
1021
-
1022
- if (buildInfo.KMeans .State == TIndexBuildInfo::TKMeans::Sample &&
1023
- !buildInfo.Sample .Rows .empty ()) {
1024
- if (buildInfo.Sample .State == TIndexBuildInfo::TSample::EState::Collect) {
1025
- LOG_D (" FillVectorIndex SendUploadSampleKRequest " << buildInfo.DebugString ());
1026
- SendUploadSampleKRequest (buildInfo);
1027
- return false ;
982
+ // (Sample -> Reshuffle)* -> MultiLocal -> NextLevel
983
+ if (buildInfo.KMeans .State == TIndexBuildInfo::TKMeans::Sample) {
984
+ return FillVectorIndexSamples (txc, buildInfo);
985
+ } else if (buildInfo.KMeans .State == TIndexBuildInfo::TKMeans::Reshuffle) {
986
+ if (NoShardsAdded (buildInfo)) {
987
+ AddGlobalShardsForCurrentParent (buildInfo);
1028
988
}
1029
- }
1030
-
1031
- LOG_D (" FillVectorIndex DoneLevel " << buildInfo.DebugString ());
1032
- ClearDoneShards (txc, buildInfo);
1033
-
1034
- if (!buildInfo.Sample .Rows .empty ()) {
1035
- if (buildInfo.KMeans .State == TIndexBuildInfo::TKMeans::Sample) {
1036
- buildInfo.KMeans .State = TIndexBuildInfo::TKMeans::Reshuffle;
1037
- LOG_D (" FillVectorIndex NextState " << buildInfo.DebugString ());
1038
- PersistKMeansState (txc, buildInfo);
1039
- Progress (BuildId);
989
+ if (!SendKMeansReshuffle (buildInfo)) {
1040
990
return false ;
1041
991
}
992
+ ClearDoneShards (txc, buildInfo);
1042
993
buildInfo.Sample .Clear ();
1043
994
NIceDb::TNiceDb db{txc.DB };
1044
995
Self->PersistBuildIndexSampleForget (db, buildInfo);
1045
- LOG_D (" FillVectorIndex DoneState " << buildInfo.DebugString ());
996
+ return FillVectorIndexNextParent (txc, buildInfo);
997
+ } else if (buildInfo.KMeans .State == TIndexBuildInfo::TKMeans::MultiLocal) {
998
+ if (!SendKMeansLocal (buildInfo)) {
999
+ return false ;
1000
+ }
1001
+ ClearDoneShards (txc, buildInfo);
1002
+ return FillVectorIndexNextParent (txc, buildInfo);
1046
1003
}
1004
+ Y_ENSURE (false );
1005
+ }
1047
1006
1048
- if (buildInfo.KMeans .NextParent ()) {
1049
- LOG_D (" FillVectorIndex NextParent " << buildInfo.DebugString ());
1007
+ bool FillVectorIndexSamples (TTransactionContext& txc, TIndexBuildInfo& buildInfo) {
1008
+ if (buildInfo.Sample .State == TIndexBuildInfo::TSample::EState::Collect) {
1009
+ if (NoShardsAdded (buildInfo)) {
1010
+ AddGlobalShardsForCurrentParent (buildInfo);
1011
+ if (!buildInfo.DoneShards .size () && !buildInfo.ToUploadShards .size ()) {
1012
+ // No "global" shards to handle - parent only has 1 shard,
1013
+ // it will be handled during the MultiLocal phase
1014
+ return FillVectorIndexNextParent (txc, buildInfo);
1015
+ }
1016
+ // Otherwise, we collect samples
1017
+ LOG_D (" FillVectorIndex Samples " << buildInfo.DebugString ());
1018
+ }
1019
+ if (!SendKMeansSample (buildInfo)) {
1020
+ return false ;
1021
+ }
1022
+ ClearDoneShards (txc, buildInfo);
1023
+ if (buildInfo.Sample .Rows .empty ()) {
1024
+ // No samples => no data for this cluster
1025
+ return FillVectorIndexNextParent (txc, buildInfo);
1026
+ }
1027
+ LOG_D (" FillVectorIndex SendUploadSampleKRequest " << buildInfo.DebugString ());
1028
+ SendUploadSampleKRequest (buildInfo);
1029
+ buildInfo.Sample .State = TIndexBuildInfo::TSample::EState::Upload;
1030
+ return false ;
1031
+ } else if (buildInfo.Sample .State == TIndexBuildInfo::TSample::EState::Upload) {
1032
+ // Just wait until samples are uploaded (saved)
1033
+ return false ;
1034
+ } else if (buildInfo.Sample .State == TIndexBuildInfo::TSample::EState::Done) {
1035
+ buildInfo.KMeans .State = TIndexBuildInfo::TKMeans::Reshuffle;
1036
+ LOG_D (" FillVectorIndex NextState " << buildInfo.DebugString ());
1050
1037
PersistKMeansState (txc, buildInfo);
1051
1038
Progress (BuildId);
1052
1039
return false ;
1053
1040
}
1041
+ Y_ENSURE (false );
1042
+ }
1054
1043
1055
- if (InitMultiKMeans (buildInfo)) {
1056
- LOG_D (" FillVectorIndex MultiKMeans " << buildInfo.DebugString ());
1044
+ bool FillVectorIndexNextParent (TTransactionContext& txc, TIndexBuildInfo& buildInfo) {
1045
+ if (buildInfo.KMeans .NextParent ()) {
1046
+ buildInfo.KMeans .State = TIndexBuildInfo::TKMeans::Sample;
1047
+ LOG_D (" FillVectorIndex NextParent " << buildInfo.DebugString ());
1057
1048
PersistKMeansState (txc, buildInfo);
1058
1049
Progress (BuildId);
1059
1050
return false ;
1060
1051
}
1061
1052
1053
+ if (!buildInfo.Cluster2Shards .empty ()) {
1054
+ AddLocalClusters (buildInfo);
1055
+ buildInfo.Cluster2Shards .clear ();
1056
+ if (!buildInfo.ToUploadShards .empty ()) {
1057
+ LOG_D (" FillVectorIndex MultiKMeans " << buildInfo.DebugString ());
1058
+ buildInfo.KMeans .State = TIndexBuildInfo::TKMeans::MultiLocal;
1059
+ PersistKMeansState (txc, buildInfo);
1060
+ Progress (BuildId);
1061
+ return false ;
1062
+ }
1063
+ }
1064
+
1062
1065
if (buildInfo.KMeans .NextLevel ()) {
1066
+ buildInfo.KMeans .State = TIndexBuildInfo::TKMeans::Sample;
1063
1067
LOG_D (" FillVectorIndex NextLevel " << buildInfo.DebugString ());
1064
1068
PersistKMeansState (txc, buildInfo);
1065
1069
NIceDb::TNiceDb db{txc.DB };
@@ -1070,6 +1074,7 @@ struct TSchemeShard::TIndexBuilder::TTxProgress: public TSchemeShard::TIndexBuil
1070
1074
Progress (BuildId);
1071
1075
return false ;
1072
1076
}
1077
+
1073
1078
LOG_D (" FillVectorIndex Done " << buildInfo.DebugString ());
1074
1079
return true ;
1075
1080
}
0 commit comments