@@ -959,15 +959,12 @@ bool DAGStorageInterpreter::checkRetriableForBatchCopOrMPP(
959959 const TableID & table_id,
960960 const SelectQueryInfo & query_info,
961961 const RegionException & e,
962- int num_allow_retry)
962+ const Int32 num_allow_retry)
963963{
964964 const DAGContext & dag_context = *context.getDAGContext ();
965965 assert ((dag_context.isBatchCop () || dag_context.isMPPTask ()));
966966 const auto & dag_regions = dag_context.getTableRegionsInfoByTableID (table_id).local_regions ;
967967 FmtBuffer buffer;
968- // Normally there is only few regions need to retry when super batch is enabled. Retry to read
969- // from local first. However, too many retry in different places may make the whole process
970- // time out of control. We limit the number of retries to 1 now.
971968 if (likely (num_allow_retry > 0 ))
972969 {
973970 auto & regions_query_info = query_info.mvcc_query_info ->regions_query_info ;
@@ -981,16 +978,22 @@ bool DAGStorageInterpreter::checkRetriableForBatchCopOrMPP(
981978 region_retry_from_local_region.emplace_back (region_iter->second );
982979 buffer.fmtAppend (" {}," , region_iter->first );
983980 }
981+ // remove the unavailable region for next local read attempt
984982 iter = regions_query_info.erase (iter);
985983 }
986984 else
987985 {
988986 ++iter;
989987 }
990988 }
989+ // `tot_num_remote_region` is the total number of regions that we will retry from other tiflash nodes among all retries
990+ // `current_retry_regions` is the number of regions that we will retry from other tiflash nodes in this retry
991991 LOG_WARNING (
992992 log,
993- " RegionException after read from storage, regions [{}], message: {}{}" ,
993+ " RegionException after read from storage, tot_num_remote_region={} cur_retry_regions={}"
994+ " regions [{}], message: {}{}" ,
995+ region_retry_from_local_region.size (),
996+ e.unavailable_region .size (),
994997 buffer.toString (),
995998 e.message (),
996999 (regions_query_info.empty () ? " " : " , retry to read from local" ));
@@ -1010,15 +1013,44 @@ bool DAGStorageInterpreter::checkRetriableForBatchCopOrMPP(
10101013 buffer.fmtAppend (" {}," , iter->first );
10111014 }
10121015 }
1016+ // `tot_num_remote_region` is the total number of regions that we will retry from other tiflash nodes among all retries
1017+ // `current_retry_regions` is the number of regions that we will retry from other tiflash nodes in this retry
10131018 LOG_WARNING (
10141019 log,
1015- " RegionException after read from storage, regions [{}], message: {}" ,
1020+ " RegionException after read from storage, tot_num_remote_region={} cur_retry_regions={}"
1021+ " regions [{}], message: {}" ,
1022+ region_retry_from_local_region.size (),
1023+ e.unavailable_region .size (),
10161024 buffer.toString (),
10171025 e.message ());
10181026 return false ; // break retry loop
10191027 }
10201028}
10211029
1030+ namespace
1031+ {
1032+ Int32 getMaxAllowRetryForLocalRead (const SelectQueryInfo & query_info)
1033+ {
1034+ size_t region_num = query_info.mvcc_query_info ->regions_query_info .size ();
1035+ if (region_num > 1000 )
1036+ {
1037+ // 1000 regions is about 93GB for 96MB region size / 250GB for 256MB region size.
1038+ return 10 ;
1039+ }
1040+ else if (region_num > 500 )
1041+ {
1042+ // 500 regions is about 46.5GB for 96MB region size / 125GB for 256MB region size.
1043+ return 8 ;
1044+ }
1045+ else if (region_num > 100 )
1046+ {
1047+ // 100 regions is about 9.3GB for 96MB region size / 25GB for 256MB region size.
1048+ return 5 ;
1049+ }
1050+ return 1 ;
1051+ }
1052+ } // namespace
1053+
10221054DM ::Remote::DisaggPhysicalTableReadSnapshotPtr DAGStorageInterpreter::buildLocalStreamsForPhysicalTable (
10231055 const TableID & table_id,
10241056 const SelectQueryInfo & query_info,
@@ -1035,7 +1067,14 @@ DM::Remote::DisaggPhysicalTableReadSnapshotPtr DAGStorageInterpreter::buildLocal
10351067
10361068 const DAGContext & dag_context = *context.getDAGContext ();
10371069 const auto keyspace_id = dag_context.getKeyspaceID ();
1038- for (int num_allow_retry = 1 ; num_allow_retry >= 0 ; --num_allow_retry)
1070+ // Normally there is only few regions need to retry when super batch is enabled. Retry to read
1071+ // from local first.
1072+ // When the table is large and too hot for writing, the number of regions may be large
1073+ // and region split is frequent. In this case, we allow more retries for building
1074+ // inputstream from local in order to avoid large number of RemoteRead requests.
1075+ // However, too many retry may make the whole execution time out of control.
1076+ Int32 num_allow_retry = getMaxAllowRetryForLocalRead (query_info);
1077+ for (; num_allow_retry >= 0 ; --num_allow_retry)
10391078 {
10401079 try
10411080 {
@@ -1077,7 +1116,7 @@ DM::Remote::DisaggPhysicalTableReadSnapshotPtr DAGStorageInterpreter::buildLocal
10771116 // clean all streams from local because we are not sure the correctness of those streams
10781117 pipeline.streams .clear ();
10791118 if (likely (checkRetriableForBatchCopOrMPP (table_id, query_info, e, num_allow_retry)))
1080- continue ;
1119+ continue ; // next retry to read from local storage
10811120 else
10821121 break ;
10831122 }
0 commit comments