Skip to content

Commit cca9dbb

Browse files
authored
fix the clear logic of specified info of one operator when print plan in explain analyze (#17454)
1 parent 3e4661b commit cca9dbb

5 files changed

Lines changed: 124 additions & 4 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.iotdb.db.it.query;
21+
22+
import org.apache.iotdb.db.queryengine.execution.operator.sink.IdentitySinkOperator;
23+
import org.apache.iotdb.db.queryengine.execution.operator.source.ExchangeOperator;
24+
import org.apache.iotdb.it.env.EnvFactory;
25+
import org.apache.iotdb.it.framework.IoTDBTestRunner;
26+
import org.apache.iotdb.itbase.category.LocalStandaloneIT;
27+
import org.apache.iotdb.itbase.env.BaseEnv;
28+
29+
import org.junit.AfterClass;
30+
import org.junit.BeforeClass;
31+
import org.junit.Test;
32+
import org.junit.experimental.categories.Category;
33+
import org.junit.runner.RunWith;
34+
35+
import java.sql.Connection;
36+
import java.sql.ResultSet;
37+
import java.sql.SQLException;
38+
import java.sql.Statement;
39+
40+
import static org.junit.Assert.assertTrue;
41+
import static org.junit.Assert.fail;
42+
43+
@RunWith(IoTDBTestRunner.class)
44+
@Category({LocalStandaloneIT.class})
45+
public class IoTDBExplainAnalyzePrintIT {
46+
47+
private static final String[] creationSqls =
48+
new String[] {
49+
"insert into root.test.device_0(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) values(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)",
50+
"insert into root.test.device_1(s11) values(11)",
51+
};
52+
53+
@BeforeClass
54+
public static void setUp() throws Exception {
55+
EnvFactory.getEnv().initClusterEnvironment();
56+
prepareData();
57+
}
58+
59+
@AfterClass
60+
public static void tearDown() throws Exception {
61+
EnvFactory.getEnv().cleanClusterEnvironment();
62+
}
63+
64+
private static void prepareData() {
65+
try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TREE_SQL_DIALECT);
66+
Statement statement = connection.createStatement()) {
67+
for (String sql : creationSqls) {
68+
statement.execute(sql);
69+
}
70+
} catch (Exception e) {
71+
fail(e.getMessage());
72+
}
73+
}
74+
75+
@Test
76+
public void testIdentitySinkOperatorWhenMergedInAnalyze() throws SQLException {
77+
try (Connection connection = EnvFactory.getEnv().getConnection();
78+
Statement statement = connection.createStatement();
79+
ResultSet resultSet =
80+
statement.executeQuery("explain analyze select * from root.test.device_0")) {
81+
boolean found = false;
82+
while (resultSet.next()) {
83+
if (resultSet.getString(1).contains(IdentitySinkOperator.DOWNSTREAM_PLAN_NODE_ID)) {
84+
found = true;
85+
break;
86+
}
87+
}
88+
assertTrue(
89+
"explain analyze output should contain DownStreamPlanNodeId in IdentitySinkOperator",
90+
found);
91+
}
92+
}
93+
94+
@Test
95+
public void testExchangeOperatorWhenMergedInAnalyze() throws SQLException {
96+
try (Connection connection = EnvFactory.getEnv().getConnection();
97+
Statement statement = connection.createStatement();
98+
ResultSet resultSet =
99+
statement.executeQuery(
100+
"explain analyze select * from root.test.device_0, root.test.device_1")) {
101+
boolean found = false;
102+
while (resultSet.next()) {
103+
if (resultSet.getString(1).contains(ExchangeOperator.SIZE_IN_BYTES)) {
104+
found = true;
105+
break;
106+
}
107+
}
108+
assertTrue("explain analyze output should contain size_in_bytes", found);
109+
}
110+
}
111+
}

integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBFilteredRowsIT.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ private void verifyExplainMetrics(
101101

102102
try (Statement statement = connection.createStatement()) {
103103
String sql = "explain analyze verbose select * from " + device + " where " + condition;
104-
log.info(sql);
105104
ResultSet resultSet = statement.executeQuery(sql);
106105

107106
StringBuilder stringBuilder = new StringBuilder();

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/FragmentInstanceExecution.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ private boolean fillFragmentInstanceStatistics(
222222
} else {
223223
String planNodeId = operatorContext.getPlanNodeId().toString();
224224
operatorStatistics.setCount(1);
225-
operatorStatistics.getSpecifiedInfo().clear();
226225
leadOverloadOperators.put(operatorType, planNodeId);
227226
operatorStatisticsMap.put(planNodeId, operatorStatistics);
228227
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/statistics/SpecifiedInfoMergerFactory.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,27 @@ public interface SpecifiedInfoMerger {
4141
return first;
4242
};
4343

44+
// currently the sink and shuffle operator only have the field of string type,
45+
// and the case that two operators contained in one FI do not exist yet
46+
private static final SpecifiedInfoMerger SINK_SHUFFLE_MERGER =
47+
(first, second) -> {
48+
first.replaceAll((k, v) -> v + " " + second.get(k));
49+
return first;
50+
};
51+
52+
/** Maintain different merge logic for specified info for different operators. */
4453
public static SpecifiedInfoMerger getMerger(String operatorType) {
4554
switch (operatorType) {
4655
case "TreeSortOperator":
4756
case "TreeMergeSortOperator":
4857
case "TableSortOperator":
4958
case "TableMergeSortOperator":
5059
case "FilterAndProjectOperator":
60+
case "ExchangeOperator":
5161
return LONG_MERGER;
62+
case "IdentitySinkOperator":
63+
case "ShuffleHelperOperator":
64+
return SINK_SHUFFLE_MERGER;
5265
default:
5366
return DEFAULT_MERGER;
5467
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/statistics/StatisticsMergeUtil.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,6 @@ public static void mergeAllOperatorStatistics(
7070
} else {
7171
TOperatorStatistics operatorStatistics = entry.getValue();
7272
operatorStatistics.setCount(1);
73-
// Can't merge specifiedInfo of String-type, so just clear it
74-
operatorStatistics.getSpecifiedInfo().clear();
7573
// keep the first one in operatorStatisticsMap as the only-one leadOverloadOperator
7674
leadOverloadOperators.put(
7775
operatorStatistics.getOperatorType(), operatorStatistics.getPlanNodeId());

0 commit comments

Comments
 (0)