[IOTDB-6337] Refine the count calculation in RegionScan framework

This commit is contained in:
YangCaiyin 2024-06-06 11:00:07 +08:00 committed by GitHub
parent 351ab3075b
commit 4c6e110e28
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 133 additions and 52 deletions

View File

@ -285,6 +285,28 @@ public class IoTDBActiveRegionScanIT {
basicShowActiveDeviceTest(sql, SHOW_DEVICES_COLUMN_NAMES, retArray); basicShowActiveDeviceTest(sql, SHOW_DEVICES_COLUMN_NAMES, retArray);
} }
@Test
public void showActiveDeviceEmptyTest() {
String sql = "show devices root.empty where time < 50";
String[] retArray = new String[] {};
basicShowActiveDeviceTest(sql, SHOW_DEVICES_COLUMN_NAMES, retArray);
sql = "count devices root.empty where time < 50";
long value = 0;
basicCountActiveDeviceTest(sql, COUNT_DEVICES_COLUMN_NAMES, value);
}
@Test
public void showActiveTimeseriesEmptyTest() {
String sql = "show timeseries root.empty where time < 50";
String[] retArray = new String[] {};
basicShowActiveDeviceTest(sql, SHOW_TIMESERIES_COLUMN_NAMES, retArray);
sql = "count timeseries root.empty where time < 50";
long value = 0;
basicCountActiveDeviceTest(sql, COUNT_TIMESERIES_COLUMN_NAMES, value);
}
@Test @Test
public void showActiveTimeseriesTest() { public void showActiveTimeseriesTest() {
String sql = "show timeseries where time = 4"; String sql = "show timeseries where time = 4";
@ -461,7 +483,6 @@ public class IoTDBActiveRegionScanIT {
try (ResultSet resultSet = statement.executeQuery(sql)) { try (ResultSet resultSet = statement.executeQuery(sql)) {
ResultSetMetaData resultSetMetaData = resultSet.getMetaData(); ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
Map<String, Integer> map = new HashMap<>();
assertEquals(1, resultSetMetaData.getColumnCount()); assertEquals(1, resultSetMetaData.getColumnCount());
assertEquals(columnName, resultSetMetaData.getColumnName(1)); assertEquals(columnName, resultSetMetaData.getColumnName(1));
int cnt = 0; int cnt = 0;

View File

@ -117,26 +117,37 @@ public class ActiveRegionScanMergeOperator extends AbstractConsumeAllOperator {
} }
} }
TimeColumnBuilder timeColumnBuilder = tsBlockBuilder.getTimeColumnBuilder(); if (!needMergeBeforeCount) {
ColumnBuilder[] valueColumnBuilders = tsBlockBuilder.getValueColumnBuilders(); for (int i = 0; i < inputOperatorsCount; i++) {
int curTsBlockRowIndex; if (inputTsBlocks[i] == null) {
for (int i = 0; i < inputOperatorsCount; i++) { continue;
if (inputTsBlocks[i] == null) { }
continue; for (int row = 0; row < maxRowCanBuild; row++) {
long childCount = inputTsBlocks[i].getValueColumns()[0].getLong(inputIndex[i] + row);
count += childCount;
inputIndex[i] += maxRowCanBuild;
}
} }
curTsBlockRowIndex = inputIndex[i]; } else {
for (int row = 0; row < maxRowCanBuild; row++) { TimeColumnBuilder timeColumnBuilder = tsBlockBuilder.getTimeColumnBuilder();
String id = ColumnBuilder[] valueColumnBuilders = tsBlockBuilder.getValueColumnBuilders();
inputTsBlocks[i].getValueColumns()[0].getBinary(curTsBlockRowIndex + row).toString(); int curTsBlockRowIndex;
if (!outputCount || needMergeBeforeCount) { for (int i = 0; i < inputOperatorsCount; i++) {
if (inputTsBlocks[i] == null) {
continue;
}
curTsBlockRowIndex = inputIndex[i];
for (int row = 0; row < maxRowCanBuild; row++) {
String id =
inputTsBlocks[i].getValueColumns()[0].getBinary(curTsBlockRowIndex + row).toString();
if (deduplicatedSet.contains(id)) { if (deduplicatedSet.contains(id)) {
continue; continue;
} }
deduplicatedSet.add(id); deduplicatedSet.add(id);
buildOneRow(i, curTsBlockRowIndex + row, timeColumnBuilder, valueColumnBuilders);
} }
buildOneRow(i, curTsBlockRowIndex + row, timeColumnBuilder, valueColumnBuilders); inputIndex[i] += maxRowCanBuild;
} }
inputIndex[i] += maxRowCanBuild;
} }
return outputCount ? returnResultIfNoMoreData() : tsBlockBuilder.build(); return outputCount ? returnResultIfNoMoreData() : tsBlockBuilder.build();
} }

View File

@ -37,6 +37,9 @@ public abstract class AbstractRegionScanDataSourceOperator extends AbstractSourc
protected boolean finished = false; protected boolean finished = false;
protected boolean outputCount;
protected long count = 0;
protected AbstractRegionScanForActiveDataUtil regionScanUtil; protected AbstractRegionScanForActiveDataUtil regionScanUtil;
protected TsBlockBuilder resultTsBlockBuilder; protected TsBlockBuilder resultTsBlockBuilder;
@ -97,16 +100,28 @@ public abstract class AbstractRegionScanDataSourceOperator extends AbstractSourc
} while (System.nanoTime() - start < maxRuntime && !resultTsBlockBuilder.isFull()); } while (System.nanoTime() - start < maxRuntime && !resultTsBlockBuilder.isFull());
finished = finished =
resultTsBlockBuilder.isEmpty() (resultTsBlockBuilder.isEmpty())
&& ((!regionScanUtil.hasMoreData() && regionScanUtil.isCurrentTsFileFinished()) && ((!regionScanUtil.hasMoreData() && regionScanUtil.isCurrentTsFileFinished())
|| isAllDataChecked()); || isAllDataChecked());
return !finished; boolean hasCachedCountValue = buildCountResultIfNeed();
return !finished || hasCachedCountValue;
} catch (IOException e) { } catch (IOException e) {
throw new IOException("Error occurs when scanning active time series.", e); throw new IOException("Error occurs when scanning active time series.", e);
} }
} }
private boolean buildCountResultIfNeed() {
if (!outputCount || !finished || count == -1) {
return false;
}
resultTsBlockBuilder.getTimeColumnBuilder().writeLong(-1);
resultTsBlockBuilder.getValueColumnBuilders()[0].writeLong(count);
resultTsBlockBuilder.declarePosition();
count = -1;
return true;
}
@Override @Override
public void close() throws Exception { public void close() throws Exception {
// do nothing // do nothing

View File

@ -51,7 +51,9 @@ public class ActiveDeviceRegionScanOperator extends AbstractRegionScanDataSource
OperatorContext operatorContext, OperatorContext operatorContext,
PlanNodeId sourceId, PlanNodeId sourceId,
Map<IDeviceID, Boolean> deviceToAlignedMap, Map<IDeviceID, Boolean> deviceToAlignedMap,
Filter timeFilter) { Filter timeFilter,
boolean outputCount) {
this.outputCount = outputCount;
this.sourceId = sourceId; this.sourceId = sourceId;
this.operatorContext = operatorContext; this.operatorContext = operatorContext;
this.deviceToAlignedMap = deviceToAlignedMap; this.deviceToAlignedMap = deviceToAlignedMap;
@ -70,26 +72,36 @@ public class ActiveDeviceRegionScanOperator extends AbstractRegionScanDataSource
@Override @Override
protected void updateActiveData() { protected void updateActiveData() {
TimeColumnBuilder timeColumnBuilder = resultTsBlockBuilder.getTimeColumnBuilder();
ColumnBuilder[] columnBuilders = resultTsBlockBuilder.getValueColumnBuilders();
List<IDeviceID> activeDevices = List<IDeviceID> activeDevices =
((RegionScanForActiveDeviceUtil) regionScanUtil).getActiveDevices(); ((RegionScanForActiveDeviceUtil) regionScanUtil).getActiveDevices();
for (IDeviceID deviceID : activeDevices) {
timeColumnBuilder.writeLong(-1); if (this.outputCount) {
columnBuilders[0].writeBinary(new Binary(deviceID.getBytes())); count += activeDevices.size();
columnBuilders[1].writeBinary( activeDevices.forEach(deviceToAlignedMap.keySet()::remove);
new Binary( } else {
String.valueOf(deviceToAlignedMap.get(deviceID)), TSFileConfig.STRING_CHARSET)); TimeColumnBuilder timeColumnBuilder = resultTsBlockBuilder.getTimeColumnBuilder();
columnBuilders[2].appendNull(); ColumnBuilder[] columnBuilders = resultTsBlockBuilder.getValueColumnBuilders();
columnBuilders[3].appendNull(); for (IDeviceID deviceID : activeDevices) {
resultTsBlockBuilder.declarePosition(); timeColumnBuilder.writeLong(-1);
deviceToAlignedMap.remove(deviceID); columnBuilders[0].writeBinary(new Binary(deviceID.getBytes()));
columnBuilders[1].writeBinary(
new Binary(
String.valueOf(deviceToAlignedMap.get(deviceID)), TSFileConfig.STRING_CHARSET));
columnBuilders[2].appendNull();
columnBuilders[3].appendNull();
resultTsBlockBuilder.declarePosition();
deviceToAlignedMap.remove(deviceID);
}
} }
} }
@Override @Override
protected List<TSDataType> getResultDataTypes() { protected List<TSDataType> getResultDataTypes() {
if (outputCount) {
return ColumnHeaderConstant.countDevicesColumnHeaders.stream()
.map(ColumnHeader::getColumnType)
.collect(Collectors.toList());
}
return ColumnHeaderConstant.showDevicesColumnHeaders.stream() return ColumnHeaderConstant.showDevicesColumnHeaders.stream()
.map(ColumnHeader::getColumnType) .map(ColumnHeader::getColumnType)
.collect(Collectors.toList()); .collect(Collectors.toList());

View File

@ -54,7 +54,9 @@ public class ActiveTimeSeriesRegionScanOperator extends AbstractRegionScanDataSo
OperatorContext operatorContext, OperatorContext operatorContext,
PlanNodeId sourceId, PlanNodeId sourceId,
Map<IDeviceID, Map<String, TimeseriesSchemaInfo>> timeSeriesToSchemasInfo, Map<IDeviceID, Map<String, TimeseriesSchemaInfo>> timeSeriesToSchemasInfo,
Filter timeFilter) { Filter timeFilter,
boolean isOutputCount) {
this.outputCount = isOutputCount;
this.operatorContext = operatorContext; this.operatorContext = operatorContext;
this.sourceId = sourceId; this.sourceId = sourceId;
this.timeSeriesToSchemasInfo = timeSeriesToSchemasInfo; this.timeSeriesToSchemasInfo = timeSeriesToSchemasInfo;
@ -95,6 +97,16 @@ public class ActiveTimeSeriesRegionScanOperator extends AbstractRegionScanDataSo
Map<IDeviceID, List<String>> activeTimeSeries = Map<IDeviceID, List<String>> activeTimeSeries =
((RegionScanForActiveTimeSeriesUtil) regionScanUtil).getActiveTimeSeries(); ((RegionScanForActiveTimeSeriesUtil) regionScanUtil).getActiveTimeSeries();
if (outputCount) {
for (Map.Entry<IDeviceID, List<String>> entry : activeTimeSeries.entrySet()) {
List<String> timeSeriesList = entry.getValue();
count += timeSeriesList.size();
removeTimeseriesListFromDevice(entry.getKey(), timeSeriesList);
}
return;
}
for (Map.Entry<IDeviceID, List<String>> entry : activeTimeSeries.entrySet()) { for (Map.Entry<IDeviceID, List<String>> entry : activeTimeSeries.entrySet()) {
IDeviceID deviceID = entry.getKey(); IDeviceID deviceID = entry.getKey();
String deviceStr = ((PlainDeviceID) deviceID).toStringID(); String deviceStr = ((PlainDeviceID) deviceID).toStringID();
@ -117,11 +129,18 @@ public class ActiveTimeSeriesRegionScanOperator extends AbstractRegionScanDataSo
checkAndAppend(schemaInfo.getDeadbandParameters(), columnBuilders[9]); // DeadbandParameters checkAndAppend(schemaInfo.getDeadbandParameters(), columnBuilders[9]); // DeadbandParameters
columnBuilders[10].writeBinary(VIEW_TYPE); // ViewType columnBuilders[10].writeBinary(VIEW_TYPE); // ViewType
resultTsBlockBuilder.declarePosition(); resultTsBlockBuilder.declarePosition();
timeSeriesInfo.remove(timeSeries);
}
if (timeSeriesInfo.isEmpty()) {
timeSeriesToSchemasInfo.remove(deviceID);
} }
removeTimeseriesListFromDevice(deviceID, timeSeriesList);
}
}
private void removeTimeseriesListFromDevice(IDeviceID deviceID, List<String> timeSeriesList) {
Map<String, TimeseriesSchemaInfo> timeSeriesInfo = timeSeriesToSchemasInfo.get(deviceID);
for (String timeSeries : timeSeriesList) {
timeSeriesInfo.remove(timeSeries);
}
if (timeSeriesInfo.isEmpty()) {
timeSeriesToSchemasInfo.remove(deviceID);
} }
} }
@ -131,6 +150,11 @@ public class ActiveTimeSeriesRegionScanOperator extends AbstractRegionScanDataSo
@Override @Override
protected List<TSDataType> getResultDataTypes() { protected List<TSDataType> getResultDataTypes() {
if (outputCount) {
return ColumnHeaderConstant.countTimeSeriesColumnHeaders.stream()
.map(ColumnHeader::getColumnType)
.collect(Collectors.toList());
}
return ColumnHeaderConstant.showTimeSeriesColumnHeaders.stream() return ColumnHeaderConstant.showTimeSeriesColumnHeaders.stream()
.map(ColumnHeader::getColumnType) .map(ColumnHeader::getColumnType)
.collect(Collectors.toList()); .collect(Collectors.toList());

View File

@ -2928,6 +2928,7 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
analyzeTimeseriesRegionScan( analyzeTimeseriesRegionScan(
showTimeSeriesStatement.getTimeCondition(), patternTree, analysis, context); showTimeSeriesStatement.getTimeCondition(), patternTree, analysis, context);
if (!hasSchema) { if (!hasSchema) {
analysis.setRespDatasetHeader(DatasetHeaderFactory.getShowTimeSeriesHeader());
return analysis; return analysis;
} }
} catch (IllegalPathException e) { } catch (IllegalPathException e) {
@ -3007,7 +3008,7 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
schemaTree.removeLogicalView(); schemaTree.removeLogicalView();
} }
private boolean analyzeDeviceRegionScan( private void analyzeDeviceRegionScan(
WhereCondition timeCondition, WhereCondition timeCondition,
PathPatternTree patternTree, PathPatternTree patternTree,
Analysis analysis, Analysis analysis,
@ -3019,7 +3020,7 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
ISchemaTree schemaTree = schemaFetcher.fetchSchemaInDeviceLevel(patternTree, context); ISchemaTree schemaTree = schemaFetcher.fetchSchemaInDeviceLevel(patternTree, context);
if (schemaTree.isEmpty()) { if (schemaTree.isEmpty()) {
analysis.setFinishQueryAfterAnalyze(true); analysis.setFinishQueryAfterAnalyze(true);
return false; return;
} }
// fetch Data partition // fetch Data partition
@ -3037,7 +3038,6 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
schemaTree, schemaTree,
context); context);
analysis.setDataPartitionInfo(dataPartition); analysis.setDataPartitionInfo(dataPartition);
return true;
} }
@Override @Override
@ -3051,12 +3051,8 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
showDevicesStatement.getPathPattern().concatNode(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD)); showDevicesStatement.getPathPattern().concatNode(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD));
if (showDevicesStatement.hasTimeCondition()) { if (showDevicesStatement.hasTimeCondition()) {
boolean hasSchema = analyzeDeviceRegionScan(
analyzeDeviceRegionScan( showDevicesStatement.getTimeCondition(), patternTree, analysis, context);
showDevicesStatement.getTimeCondition(), patternTree, analysis, context);
if (!hasSchema) {
return analysis;
}
} else { } else {
SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree); SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
analysis.setSchemaPartitionInfo(schemaPartitionInfo); analysis.setSchemaPartitionInfo(schemaPartitionInfo);
@ -3117,12 +3113,8 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
patternTree.appendPathPattern( patternTree.appendPathPattern(
countDevicesStatement.getPathPattern().concatNode(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD)); countDevicesStatement.getPathPattern().concatNode(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD));
if (countDevicesStatement.hasTimeCondition()) { if (countDevicesStatement.hasTimeCondition()) {
boolean hasSchema = analyzeDeviceRegionScan(
analyzeDeviceRegionScan( countDevicesStatement.getTimeCondition(), patternTree, analysis, context);
countDevicesStatement.getTimeCondition(), patternTree, analysis, context);
if (!hasSchema) {
return analysis;
}
} else { } else {
SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree); SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
analysis.setSchemaPartitionInfo(schemaPartitionInfo); analysis.setSchemaPartitionInfo(schemaPartitionInfo);
@ -3147,6 +3139,7 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
analyzeTimeseriesRegionScan( analyzeTimeseriesRegionScan(
countTimeSeriesStatement.getTimeCondition(), patternTree, analysis, context); countTimeSeriesStatement.getTimeCondition(), patternTree, analysis, context);
if (!hasSchema) { if (!hasSchema) {
analysis.setRespDatasetHeader(DatasetHeaderFactory.getCountTimeSeriesHeader());
return analysis; return analysis;
} }
} catch (IllegalPathException e) { } catch (IllegalPathException e) {

View File

@ -3540,7 +3540,7 @@ public class OperatorTreeGenerator extends PlanVisitor<Operator, LocalExecutionP
} }
ActiveDeviceRegionScanOperator regionScanOperator = ActiveDeviceRegionScanOperator regionScanOperator =
new ActiveDeviceRegionScanOperator( new ActiveDeviceRegionScanOperator(
operatorContext, node.getPlanNodeId(), deviceIDToAligned, filter); operatorContext, node.getPlanNodeId(), deviceIDToAligned, filter, node.isOutputCount());
DataDriverContext dataDriverContext = (DataDriverContext) context.getDriverContext(); DataDriverContext dataDriverContext = (DataDriverContext) context.getDriverContext();
dataDriverContext.addSourceOperator(regionScanOperator); dataDriverContext.addSourceOperator(regionScanOperator);
@ -3573,7 +3573,11 @@ public class OperatorTreeGenerator extends PlanVisitor<Operator, LocalExecutionP
} }
ActiveTimeSeriesRegionScanOperator regionScanOperator = ActiveTimeSeriesRegionScanOperator regionScanOperator =
new ActiveTimeSeriesRegionScanOperator( new ActiveTimeSeriesRegionScanOperator(
operatorContext, node.getPlanNodeId(), timeseriesToSchemaInfo, filter); operatorContext,
node.getPlanNodeId(),
timeseriesToSchemaInfo,
filter,
node.isOutputCount());
dataDriverContext.addSourceOperator(regionScanOperator); dataDriverContext.addSourceOperator(regionScanOperator);
dataDriverContext.setQueryDataSourceType(QueryDataSourceType.TIME_SERIES_REGION_SCAN); dataDriverContext.setQueryDataSourceType(QueryDataSourceType.TIME_SERIES_REGION_SCAN);

View File

@ -774,6 +774,7 @@ public class SourceRewriter extends BaseSourceRewriter<DistributionPlanContext>
RegionScanNode regionScanNode = (RegionScanNode) node.clone(); RegionScanNode regionScanNode = (RegionScanNode) node.clone();
regionScanNode.setPlanNodeId(context.queryContext.getQueryId().genPlanNodeId()); regionScanNode.setPlanNodeId(context.queryContext.getQueryId().genPlanNodeId());
regionScanNode.setRegionReplicaSet(dataRegion); regionScanNode.setRegionReplicaSet(dataRegion);
regionScanNode.setOutputCount(node.isOutputCount());
regionScanNode.clearPath(); regionScanNode.clearPath();
return regionScanNode; return regionScanNode;
}) })