diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java index 08f7c8efc92b0a..fd0d219cf9acd0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java @@ -1007,22 +1007,14 @@ private void computeTabletInfo() throws UserException { */ Preconditions.checkState(scanBackendIds.isEmpty()); Preconditions.checkState(scanTabletIds.isEmpty()); - Map> backendAlivePathHashs = Maps.newHashMap(); - for (Backend backend : olapTable.getAllBackendsByAllCluster().values()) { - Set hashSet = Sets.newLinkedHashSet(); - for (DiskInfo diskInfo : backend.getDisks().values()) { - if (diskInfo.isAlive()) { - hashSet.add(diskInfo.getPathHash()); - } - } - backendAlivePathHashs.put(backend.getId(), hashSet); - } - ConnectContext connectContext = ConnectContext.get(); boolean isNereids = connectContext != null && connectContext.getState().isNereids(); boolean isPointQuery = connectContext != null && connectContext.getStatementContext() != null && connectContext.getStatementContext().isShortCircuitQuery(); + ImmutableMap allBackends = olapTable.getAllBackendsByAllCluster(); + Map> backendAlivePathHashes = isPointQuery + ? null : getBackendAlivePathHashes(allBackends.values()); for (Long partitionId : selectedPartitionIds) { final Partition partition = olapTable.getPartition(partitionId); final MaterializedIndex selectedTable = olapTable.getPartitionIndex(partition, selectedIndexId); @@ -1070,7 +1062,7 @@ private void computeTabletInfo() throws UserException { scanTabletIds.addAll(allTabletIds); } - if (!isPointQuery()) { + if (!isPointQuery) { int bucketNum = partition.getDistributionInfo().getBucketNum(); for (int i = 0; i < allTabletIds.size(); i++) { tabletId2BucketInfo.put(allTabletIds.get(i), encodeBucketInfo(i, bucketNum)); @@ -1079,8 +1071,46 @@ private void computeTabletInfo() throws UserException { totalTabletsNum += selectedTable.getTablets().size(); selectedSplitNum += tablets.size(); - addScanRangeLocations(partition, tablets, backendAlivePathHashs); + Map> currentBackendAlivePathHashes = isPointQuery + ? getBackendAlivePathHashes(allBackends, tablets) : backendAlivePathHashes; + addScanRangeLocations(partition, tablets, currentBackendAlivePathHashes); + } + } + + private static Map> getBackendAlivePathHashes(Collection backends) { + Map> backendAlivePathHashes = Maps.newHashMap(); + for (Backend backend : backends) { + backendAlivePathHashes.put(backend.getId(), getBackendAlivePathHashes(backend)); + } + return backendAlivePathHashes; + } + + @VisibleForTesting + static Map> getBackendAlivePathHashes( + Map backends, List tablets) { + Map> backendAlivePathHashes = Maps.newHashMap(); + for (Tablet tablet : tablets) { + for (Replica replica : tablet.getReplicas()) { + long backendId = replica.getBackendIdWithoutException(); + Backend backend = backends.get(backendId); + if (backend != null) { + backendAlivePathHashes.computeIfAbsent( + backendId, id -> getBackendAlivePathHashes(backend)); + } + } + } + return backendAlivePathHashes; + } + + private static Set getBackendAlivePathHashes(Backend backend) { + Map disks = backend.getDisks(); + Set alivePathHashes = Sets.newHashSetWithExpectedSize(disks.size()); + for (DiskInfo diskInfo : disks.values()) { + if (diskInfo.isAlive()) { + alivePathHashes.add(diskInfo.getPathHash()); + } } + return alivePathHashes; } /** diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/OlapScanNodeTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/OlapScanNodeTest.java index c18b821ec116e4..30a0d097d4a8ca 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/planner/OlapScanNodeTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/planner/OlapScanNodeTest.java @@ -28,23 +28,30 @@ import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.analysis.TupleId; import org.apache.doris.catalog.Column; +import org.apache.doris.catalog.DiskInfo; +import org.apache.doris.catalog.LocalReplica; +import org.apache.doris.catalog.LocalTablet; import org.apache.doris.catalog.OlapTable; import org.apache.doris.catalog.Partition; import org.apache.doris.catalog.PartitionKey; import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.catalog.RangePartitionInfo; import org.apache.doris.catalog.RangePartitionItem; +import org.apache.doris.catalog.Replica.ReplicaState; +import org.apache.doris.catalog.Tablet; import org.apache.doris.catalog.info.TableNameInfo; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.Config; import org.apache.doris.common.util.DebugPointUtil; import org.apache.doris.datasource.InternalCatalog; +import org.apache.doris.system.Backend; import org.apache.doris.thrift.TOlapScanNode; import org.apache.doris.thrift.TPaloScanRange; import org.apache.doris.thrift.TPartitionBoundary; import org.apache.doris.thrift.TScanRange; import org.apache.doris.thrift.TScanRangeLocations; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Range; @@ -59,6 +66,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; public class OlapScanNodeTest { @@ -356,6 +364,45 @@ private Map getBucketInfo(OlapScanNode scanNode) throws Exception { return (Map) bucketInfoField.get(scanNode); } + @Test + public void testPointQueryBackendAlivePathsOnlyUseSelectedTabletBackends() { + Backend firstBackend = backendWithDisks(1L, 11L, 12L); + Backend secondBackend = backendWithDisks(2L, 21L, 22L); + Backend unrelatedBackend = backendWithDisks(3L, 31L, 32L); + Map backends = ImmutableMap.of( + firstBackend.getId(), firstBackend, + secondBackend.getId(), secondBackend, + unrelatedBackend.getId(), unrelatedBackend); + + LocalTablet selectedTablet = new LocalTablet(10L); + selectedTablet.addReplica(new LocalReplica(101L, firstBackend.getId(), 0, ReplicaState.NORMAL), true); + selectedTablet.addReplica(new LocalReplica(102L, secondBackend.getId(), 0, ReplicaState.NORMAL), true); + selectedTablet.addReplica(new LocalReplica(103L, 4L, 0, ReplicaState.NORMAL), true); + + Map> alivePathHashes = OlapScanNode.getBackendAlivePathHashes( + backends, Lists.newArrayList(selectedTablet)); + + Assert.assertEquals(2, alivePathHashes.size()); + Assert.assertEquals(Collections.singleton(11L), alivePathHashes.get(firstBackend.getId())); + Assert.assertEquals(Collections.singleton(21L), alivePathHashes.get(secondBackend.getId())); + Assert.assertFalse(alivePathHashes.containsKey(unrelatedBackend.getId())); + Assert.assertFalse(alivePathHashes.containsKey(4L)); + } + + private Backend backendWithDisks(long backendId, long alivePathHash, long offlinePathHash) { + DiskInfo aliveDisk = new DiskInfo("/alive-" + backendId); + aliveDisk.setPathHash(alivePathHash); + DiskInfo offlineDisk = new DiskInfo("/offline-" + backendId); + offlineDisk.setPathHash(offlinePathHash); + offlineDisk.setState(DiskInfo.DiskState.OFFLINE); + + Backend backend = new Backend(backendId, "127.0.0." + backendId, 9050); + backend.setDisks(ImmutableMap.of( + aliveDisk.getRootPath(), aliveDisk, + offlineDisk.getRootPath(), offlineDisk)); + return backend; + } + private Partition mockPartition(String name) { Partition partition = Mockito.mock(Partition.class); Mockito.when(partition.getName()).thenReturn(name);