This is an automated email from the ASF dual-hosted git repository.
haonan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 2600bf8 [IOTDB-749] Handle select * from root OOM (#1367)
2600bf8 is described below
commit 2600bf840bd7b4dd52b73466c09a34eb8c32564c
Author: Jackie Tien <[email protected]>
AuthorDate: Fri Oct 23 17:49:44 2020 +0800
[IOTDB-749] Handle select * from root OOM (#1367)
Co-authored-by: xiangdong huang <[email protected]>
---
.../resources/conf/iotdb-engine.properties | 10 ++--
.../java/org/apache/iotdb/db/conf/IoTDBConfig.java | 23 ++++++++
.../org/apache/iotdb/db/conf/IoTDBDescriptor.java | 39 ++++++++------
.../exception/query/PathNumOverLimitException.java | 35 ++++++++++++
.../org/apache/iotdb/db/metadata/MManager.java | 14 ++---
.../java/org/apache/iotdb/db/metadata/MTree.java | 27 ++++++++--
.../main/java/org/apache/iotdb/db/qp/Planner.java | 33 +++++++-----
.../iotdb/db/qp/strategy/PhysicalGenerator.java | 53 +++++++++++-------
.../qp/strategy/optimizer/ConcatPathOptimizer.java | 50 +++++++++--------
.../qp/strategy/optimizer/ILogicalOptimizer.java | 4 +-
.../db/query/control/QueryResourceManager.java | 49 +++++++++++++++--
.../org/apache/iotdb/db/service/TSServiceImpl.java | 62 +++++++++++++++-------
.../db/integration/IoTDBSequenceDataQueryIT.java | 9 ++--
.../iotdb/db/integration/IoTDBSeriesReaderIT.java | 11 ++--
.../org/apache/iotdb/db/metadata/MTreeTest.java | 6 +--
.../iotdb/db/qp/plan/LogicalPlanSmallTest.java | 2 +-
.../apache/iotdb/db/utils/EnvironmentUtils.java | 15 +++---
.../apache/iotdb/spark/db/EnvironmentUtils.java | 14 ++---
18 files changed, 324 insertions(+), 132 deletions(-)
diff --git a/server/src/assembly/resources/conf/iotdb-engine.properties
b/server/src/assembly/resources/conf/iotdb-engine.properties
index 7810559..5332cff 100644
--- a/server/src/assembly/resources/conf/iotdb-engine.properties
+++ b/server/src/assembly/resources/conf/iotdb-engine.properties
@@ -236,6 +236,10 @@ write_read_free_memory_proportion=6:3:1
# primitive array size (length of each array) in array pool
primitive_array_size=128
+# allowed max numbers of deduplicated path in one query
+# it's just an advised value, the real limitation will be the smaller one
between this and the one we calculated
+max_deduplicated_path_num=1000
+
####################
### Upgrade Configurations
####################
@@ -340,9 +344,9 @@ merge_read_throughput_mb_per_sec=16
# whether to cache meta data(ChunkMetadata and TimeSeriesMetadata) or not.
meta_data_cache_enable=true
-# Read memory Allocation Ratio: ChunkMetadataCache, ChunkCache,
TimeSeriesMetadataCache and Free Memory Used in Query.
-# The parameter form is a:b:c:d, where a, b, c and d are integers. for
example: 1:1:1:1 , 6:10:5:15
-chunkmeta_chunk_timeseriesmeta_free_memory_proportion=1:1:1:7
+# Read memory Allocation Ratio: ChunkMetadataCache, ChunkCache,
TimeSeriesMetadataCache, memory used for constructing QueryDataSet and Free
Memory Used in Query.
+# The parameter form is a:b:c:d:e, where a, b, c, d and e are integers. for
example: 1:1:1:1:1 , 1:1:1:3:4
+chunkmeta_chunk_timeseriesmeta_free_memory_proportion=1:1:1:3:4
# cache size for MManager.
# This cache is used to improve insert speed where all path check and
TSDataType will be cached in MManager with corresponding Path.
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
index ee06c00..c65b744 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
@@ -131,6 +131,13 @@ public class IoTDBConfig {
private long allocateMemoryForRead = Runtime.getRuntime().maxMemory() * 3 /
10;
/**
+ * Memory allocated for the read process besides cache
+ */
+ private long allocateMemoryForReadWithoutCache =
Runtime.getRuntime().maxMemory() * 9 / 100;
+
+ private volatile int maxQueryDeduplicatedPathNum = 1000;
+
+ /**
* Is dynamic parameter adapter enable.
*/
private boolean enableParameterAdapter = true;
@@ -1195,6 +1202,14 @@ public class IoTDBConfig {
this.allocateMemoryForRead = allocateMemoryForRead;
}
+ public long getAllocateMemoryForReadWithoutCache() {
+ return allocateMemoryForReadWithoutCache;
+ }
+
+ public void setAllocateMemoryForReadWithoutCache(long
allocateMemoryForReadWithoutCache) {
+ this.allocateMemoryForReadWithoutCache = allocateMemoryForReadWithoutCache;
+ }
+
public boolean isEnableExternalSort() {
return enableExternalSort;
}
@@ -1858,4 +1873,12 @@ public class IoTDBConfig {
public long getStartUpNanosecond() {
return startUpNanosecond;
}
+
+ public int getMaxQueryDeduplicatedPathNum() {
+ return maxQueryDeduplicatedPathNum;
+ }
+
+ public void setMaxQueryDeduplicatedPathNum(int maxQueryDeduplicatedPathNum) {
+ this.maxQueryDeduplicatedPathNum = maxQueryDeduplicatedPathNum;
+ }
}
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
index a552d64..7b324d7 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
@@ -98,7 +98,8 @@ public class IoTDBDescriptor {
if (urlString == null) {
urlString = System.getProperty(IoTDBConstant.IOTDB_HOME, null);
if (urlString != null) {
- urlString = urlString + File.separatorChar + "conf" +
File.separatorChar + IoTDBConfig.CONFIG_NAME;
+ urlString =
+ urlString + File.separatorChar + "conf" + File.separatorChar +
IoTDBConfig.CONFIG_NAME;
} else {
// If this too wasn't provided, try to find a default config in the
root of the classpath.
URL uri = IoTDBConfig.class.getResource("/" + IoTDBConfig.CONFIG_NAME);
@@ -116,13 +117,13 @@ public class IoTDBDescriptor {
}
// If a config location was provided, but it doesn't end with a properties
file,
// append the default location.
- else if(!urlString.endsWith(".properties")) {
+ else if (!urlString.endsWith(".properties")) {
urlString += (File.separatorChar + IoTDBConfig.CONFIG_NAME);
}
// If the url doesn't start with "file:" or "classpath:", it's provided as
a normal path.
// So we need to add it to make it a real URL.
- if(!urlString.startsWith("file:") && !urlString.startsWith("classpath:")) {
+ if (!urlString.startsWith("file:") && !urlString.startsWith("classpath:"))
{
urlString = "file:" + urlString;
}
try {
@@ -138,7 +139,7 @@ public class IoTDBDescriptor {
@SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity
warning
private void loadProps() {
URL url = getPropsUrl();
- if(url == null) {
+ if (url == null) {
logger.warn("Couldn't load the configuration from any of the known
sources.");
return;
}
@@ -207,7 +208,7 @@ public class IoTDBDescriptor {
Boolean.toString(conf.isMetaDataCacheEnable()))));
conf.setEnableLastCache(Boolean.parseBoolean(properties.getProperty("enable_last_cache",
- Boolean.toString(conf.isLastCacheEnabled()))));
+ Boolean.toString(conf.isLastCacheEnabled()))));
initMemoryAllocate(properties);
@@ -563,7 +564,7 @@ public class IoTDBDescriptor {
conf.setEnableDiscardOutOfOrderData(Boolean.parseBoolean(
properties.getProperty("enable_discard_out_of_order_data",
- Boolean.toString(conf.isEnableDiscardOutOfOrderData()))));
+ Boolean.toString(conf.isEnableDiscardOutOfOrderData()))));
}
@@ -696,6 +697,10 @@ public class IoTDBDescriptor {
// update tsfile-format config
loadTsFileProps(properties);
+ // update max_deduplicated_path_num
+ conf.setMaxQueryDeduplicatedPathNum(
+
Integer.parseInt(properties.getProperty("max_deduplicated_path_num")));
+
} catch (Exception e) {
throw new QueryProcessException(
String.format("Fail to reload configuration because %s", e));
@@ -704,7 +709,7 @@ public class IoTDBDescriptor {
public void loadHotModifiedProps() throws QueryProcessException {
URL url = getPropsUrl();
- if(url == null) {
+ if (url == null) {
logger.warn("Couldn't load the configuration from any of the known
sources.");
return;
}
@@ -732,9 +737,9 @@ public class IoTDBDescriptor {
long maxMemoryAvailable = Runtime.getRuntime().maxMemory();
if (proportionSum != 0) {
conf.setAllocateMemoryForWrite(
- maxMemoryAvailable * Integer.parseInt(proportions[0].trim()) /
proportionSum);
+ maxMemoryAvailable * Integer.parseInt(proportions[0].trim()) /
proportionSum);
conf.setAllocateMemoryForRead(
- maxMemoryAvailable * Integer.parseInt(proportions[1].trim()) /
proportionSum);
+ maxMemoryAvailable * Integer.parseInt(proportions[1].trim()) /
proportionSum);
}
}
@@ -757,19 +762,23 @@ public class IoTDBDescriptor {
if (proportionSum != 0) {
try {
conf.setAllocateMemoryForChunkMetaDataCache(
- maxMemoryAvailable * Integer.parseInt(proportions[0].trim())
/ proportionSum);
+ maxMemoryAvailable * Integer.parseInt(proportions[0].trim()) /
proportionSum);
conf.setAllocateMemoryForChunkCache(
- maxMemoryAvailable * Integer.parseInt(proportions[1].trim())
/ proportionSum);
+ maxMemoryAvailable * Integer.parseInt(proportions[1].trim()) /
proportionSum);
conf.setAllocateMemoryForTimeSeriesMetaDataCache(
- maxMemoryAvailable * Integer.parseInt(proportions[2].trim())
/ proportionSum);
+ maxMemoryAvailable * Integer.parseInt(proportions[2].trim()) /
proportionSum);
+ conf.setAllocateMemoryForReadWithoutCache(
+ maxMemoryAvailable * Integer.parseInt(proportions[3].trim()) /
proportionSum);
} catch (Exception e) {
throw new RuntimeException(
- "Each subsection of configuration item
chunkmeta_chunk_timeseriesmeta_free_memory_proportion"
- + " should be an integer, which is "
- + queryMemoryAllocateProportion);
+ "Each subsection of configuration item
chunkmeta_chunk_timeseriesmeta_free_memory_proportion"
+ + " should be an integer, which is "
+ + queryMemoryAllocateProportion);
}
}
+ conf.setMaxQueryDeduplicatedPathNum(
+
Integer.parseInt(properties.getProperty("max_deduplicated_path_num")));
}
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/exception/query/PathNumOverLimitException.java
b/server/src/main/java/org/apache/iotdb/db/exception/query/PathNumOverLimitException.java
new file mode 100644
index 0000000..6829d68
--- /dev/null
+++
b/server/src/main/java/org/apache/iotdb/db/exception/query/PathNumOverLimitException.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.exception.query;
+
+public class PathNumOverLimitException extends QueryProcessException {
+
+ public PathNumOverLimitException(long maxDeduplicatedPathNum, long
deduplicatedPathNum) {
+ super(String.format(
+ "Too many paths in one query! Currently allowed max deduplicated path
number is %d, this query contains %d deduplicated path. Please use slimit to
choose what you real want or adjust max_deduplicated_path_num in
iotdb-engine.properties.",
+ maxDeduplicatedPathNum, deduplicatedPathNum));
+ }
+
+ public PathNumOverLimitException(long maxDeduplicatedPathNum) {
+ super(String.format(
+ "Too many paths in one query! Currently allowed max deduplicated path
number is %d, this query contains unknown deduplicated path. Please use slimit
to choose what you real want or adjust max_deduplicated_path_num in
iotdb-engine.properties.",
+ maxDeduplicatedPathNum));
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
index efeb4af..f4c6c3f 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
@@ -737,9 +737,9 @@ public class MManager {
/**
* Similar to method getAllTimeseriesPath(), but return Path with alias
alias.
*/
- public List<PartialPath> getAllTimeseriesPathWithAlias(PartialPath
prefixPath)
- throws MetadataException {
- return mtree.getAllTimeseriesPathWithAlias(prefixPath);
+ public Pair<List<PartialPath>, Integer>
getAllTimeseriesPathWithAlias(PartialPath prefixPath,
+ int limit, int offset) throws MetadataException {
+ return mtree.getAllTimeseriesPathWithAlias(prefixPath, limit, offset);
}
/**
@@ -1715,7 +1715,8 @@ public class MManager {
internalCreateTimeseries(deviceId.concatNode(measurementList[i]),
dataType);
}
- MeasurementMNode measurementMNode = (MeasurementMNode)
deviceMNode.getChild(measurementList[i]);
+ MeasurementMNode measurementMNode = (MeasurementMNode) deviceMNode
+ .getChild(measurementList[i]);
// check type is match
TSDataType insertDataType = null;
@@ -1778,8 +1779,9 @@ public class MManager {
Collections.emptyMap());
} catch (PathAlreadyExistException | AliasAlreadyExistException e) {
if (logger.isDebugEnabled()) {
- logger.debug("Ignore PathAlreadyExistException and
AliasAlreadyExistException when Concurrent inserting"
- + " a non-exist time series {}", path);
+ logger.debug(
+ "Ignore PathAlreadyExistException and AliasAlreadyExistException
when Concurrent inserting"
+ + " a non-exist time series {}", path);
}
}
}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
b/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
index 1fa8160..387c7b5 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
@@ -776,11 +776,16 @@ public class MTree implements Serializable {
* Get all timeseries paths under the given path
*
* @param prefixPath a prefix path or a full path, may contain '*'.
+ *
+ * @return Pair.left contains all the satisfied paths
+ * Pair.right means the current offset or zero if we don't set
offset.
*/
- List<PartialPath> getAllTimeseriesPathWithAlias(PartialPath prefixPath)
throws MetadataException {
+ Pair<List<PartialPath>, Integer> getAllTimeseriesPathWithAlias(PartialPath
prefixPath, int limit, int offset) throws MetadataException {
PartialPath prePath = new PartialPath(prefixPath.getNodes());
ShowTimeSeriesPlan plan = new ShowTimeSeriesPlan(prefixPath);
- List<Pair<PartialPath, String[]>> res = getAllMeasurementSchema(plan);
+ plan.setLimit(limit);
+ plan.setOffset(offset);
+ List<Pair<PartialPath, String[]>> res = getAllMeasurementSchema(plan,
false);
List<PartialPath> paths = new ArrayList<>();
for (Pair<PartialPath, String[]> p : res) {
if (prePath.getMeasurement().equals(p.right[0])) {
@@ -788,7 +793,13 @@ public class MTree implements Serializable {
}
paths.add(p.left);
}
- return paths;
+ if (curOffset.get() == null) {
+ offset = 0;
+ } else {
+ offset = curOffset.get() + 1;
+ }
+ curOffset.remove();
+ return new Pair<>(paths, offset);
}
/**
@@ -986,6 +997,12 @@ public class MTree implements Serializable {
*/
List<Pair<PartialPath, String[]>> getAllMeasurementSchema(ShowTimeSeriesPlan
plan)
throws MetadataException {
+ return getAllMeasurementSchema(plan, true);
+ }
+
+
+ List<Pair<PartialPath, String[]>> getAllMeasurementSchema(ShowTimeSeriesPlan
plan, boolean removeCurrentOffset)
+ throws MetadataException {
List<Pair<PartialPath, String[]>> res;
String[] nodes = plan.getPath().getNodes();
if (nodes.length == 0 || !nodes[0].equals(root.getName())) {
@@ -1005,7 +1022,9 @@ public class MTree implements Serializable {
// avoid memory leaks
limit.remove();
offset.remove();
- curOffset.remove();
+ if (removeCurrentOffset) {
+ curOffset.remove();
+ }
count.remove();
return res;
}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
b/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
index 3d005e9..b8632d2 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
@@ -29,6 +29,7 @@ import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.exception.metadata.IllegalPathException;
import org.apache.iotdb.db.exception.query.LogicalOperatorException;
import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
+import org.apache.iotdb.db.exception.query.PathNumOverLimitException;
import org.apache.iotdb.db.exception.query.QueryProcessException;
import org.apache.iotdb.db.metadata.PartialPath;
import org.apache.iotdb.db.qp.constant.SQLConstant;
@@ -46,6 +47,7 @@ import
org.apache.iotdb.db.qp.strategy.optimizer.ConcatPathOptimizer;
import org.apache.iotdb.db.qp.strategy.optimizer.DnfFilterOptimizer;
import org.apache.iotdb.db.qp.strategy.optimizer.MergeSingleFilterOptimizer;
import org.apache.iotdb.db.qp.strategy.optimizer.RemoveNotOptimizer;
+import org.apache.iotdb.db.query.control.QueryResourceManager;
import org.apache.iotdb.db.utils.TestOnly;
import org.apache.iotdb.service.rpc.thrift.TSRawDataQueryReq;
@@ -64,15 +66,20 @@ public class Planner {
public PhysicalPlan parseSQLToPhysicalPlan(String sqlStr)
throws QueryProcessException {
IoTDBConfig config = IoTDBDescriptor.getInstance().getConfig();
- return parseSQLToPhysicalPlan(sqlStr, config.getZoneID());
+ return parseSQLToPhysicalPlan(sqlStr, config.getZoneID(), 1024);
}
- public PhysicalPlan parseSQLToPhysicalPlan(String sqlStr, ZoneId zoneId)
+ /**
+ * @param fetchSize this parameter only take effect when it is a query plan
+ */
+ public PhysicalPlan parseSQLToPhysicalPlan(String sqlStr, ZoneId zoneId, int
fetchSize)
throws QueryProcessException {
Operator operator = parseDriver.parse(sqlStr, zoneId);
- operator = logicalOptimize(operator);
+ int maxDeduplicatedPathNum = QueryResourceManager.getInstance()
+ .getMaxDeduplicatedPathNum(fetchSize);
+ operator = logicalOptimize(operator, maxDeduplicatedPathNum);
PhysicalGenerator physicalGenerator = new PhysicalGenerator();
- return physicalGenerator.transformToPhysicalPlan(operator);
+ return physicalGenerator.transformToPhysicalPlan(operator, fetchSize);
}
/**
@@ -115,9 +122,11 @@ public class Planner {
queryOp.setFilterOperator(filterOp);
- SFWOperator op = (SFWOperator) logicalOptimize(queryOp);
+ int maxDeduplicatedPathNum = QueryResourceManager.getInstance()
+ .getMaxDeduplicatedPathNum(rawDataQueryReq.fetchSize);
+ SFWOperator op = (SFWOperator) logicalOptimize(queryOp,
maxDeduplicatedPathNum);
PhysicalGenerator physicalGenerator = new PhysicalGenerator();
- return physicalGenerator.transformToPhysicalPlan(op);
+ return physicalGenerator.transformToPhysicalPlan(op,
rawDataQueryReq.fetchSize);
}
/**
@@ -127,8 +136,8 @@ public class Planner {
* @return optimized logical operator
* @throws LogicalOptimizeException exception in logical optimizing
*/
- protected Operator logicalOptimize(Operator operator)
- throws LogicalOperatorException {
+ protected Operator logicalOptimize(Operator operator, int
maxDeduplicatedPathNum)
+ throws LogicalOperatorException, PathNumOverLimitException {
switch (operator.getType()) {
case AUTHOR:
case METADATA:
@@ -162,7 +171,7 @@ public class Planner {
case UPDATE:
case DELETE:
SFWOperator root = (SFWOperator) operator;
- return optimizeSFWOperator(root);
+ return optimizeSFWOperator(root, maxDeduplicatedPathNum);
default:
throw new LogicalOperatorException(operator.getType().toString(), "");
}
@@ -175,10 +184,10 @@ public class Planner {
* @return optimized select-from-where operator
* @throws LogicalOptimizeException exception in SFW optimizing
*/
- private SFWOperator optimizeSFWOperator(SFWOperator root)
- throws LogicalOperatorException {
+ private SFWOperator optimizeSFWOperator(SFWOperator root, int
maxDeduplicatedPathNum)
+ throws LogicalOperatorException, PathNumOverLimitException {
ConcatPathOptimizer concatPathOptimizer = getConcatPathOptimizer();
- root = (SFWOperator) concatPathOptimizer.transform(root);
+ root = (SFWOperator) concatPathOptimizer.transform(root,
maxDeduplicatedPathNum);
FilterOperator filter = root.getFilterOperator();
if (filter == null) {
return root;
diff --git
a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
index 6a721e3..3aaab37 100644
---
a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
+++
b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.iotdb.db.auth.AuthException;
import org.apache.iotdb.db.exception.metadata.MetadataException;
+import org.apache.iotdb.db.exception.query.PathNumOverLimitException;
import org.apache.iotdb.db.exception.query.LogicalOperatorException;
import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
import org.apache.iotdb.db.exception.query.QueryProcessException;
@@ -102,6 +103,7 @@ import
org.apache.iotdb.db.qp.physical.sys.ShowPlan.ShowContentType;
import org.apache.iotdb.db.qp.physical.sys.ShowStorageGroupPlan;
import org.apache.iotdb.db.qp.physical.sys.ShowTTLPlan;
import org.apache.iotdb.db.qp.physical.sys.ShowTimeSeriesPlan;
+import org.apache.iotdb.db.query.control.QueryResourceManager;
import org.apache.iotdb.db.qp.physical.sys.TracingPlan;
import org.apache.iotdb.db.service.IoTDB;
import org.apache.iotdb.db.utils.SchemaUtils;
@@ -115,8 +117,10 @@ import org.apache.iotdb.tsfile.utils.Pair;
*/
public class PhysicalGenerator {
+
@SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity
warning
- public PhysicalPlan transformToPhysicalPlan(Operator operator) throws
QueryProcessException {
+ public PhysicalPlan transformToPhysicalPlan(Operator operator, int fetchSize)
+ throws QueryProcessException {
List<PartialPath> paths;
switch (operator.getType()) {
case AUTHOR:
@@ -144,10 +148,9 @@ public class PhysicalGenerator {
return new
DeleteStorageGroupPlan(deleteStorageGroup.getDeletePathList());
case CREATE_TIMESERIES:
CreateTimeSeriesOperator createOperator = (CreateTimeSeriesOperator)
operator;
- if (createOperator.getTags() != null
- && !createOperator.getTags().isEmpty()
- && createOperator.getAttributes() != null
- && !createOperator.getAttributes().isEmpty()) {
+ if (createOperator.getTags() != null &&
!createOperator.getTags().isEmpty()
+ && createOperator.getAttributes() != null &&
!createOperator.getAttributes()
+ .isEmpty()) {
for (String tagKey : createOperator.getTags().keySet()) {
if (createOperator.getAttributes().containsKey(tagKey)) {
throw new QueryProcessException(
@@ -198,7 +201,7 @@ public class PhysicalGenerator {
return new TracingPlan(tracingOperator.isTracingon());
case QUERY:
QueryOperator query = (QueryOperator) operator;
- return transformQuery(query);
+ return transformQuery(query, fetchSize);
case TTL:
switch (operator.getTokenIntType()) {
case SQLConstant.TOK_SET:
@@ -211,9 +214,8 @@ public class PhysicalGenerator {
ShowTTLOperator showTTLOperator = (ShowTTLOperator) operator;
return new ShowTTLPlan(showTTLOperator.getStorageGroups());
default:
- throw new LogicalOperatorException(
- String.format(
- "not supported operator type %s in ttl operation.",
operator.getType()));
+ throw new LogicalOperatorException(String
+ .format("not supported operator type %s in ttl operation.",
operator.getType()));
}
case LOAD_CONFIGURATION:
LoadConfigurationOperatorType type = ((LoadConfigurationOperator)
operator)
@@ -246,14 +248,10 @@ public class PhysicalGenerator {
return new CountPlan(
ShowContentType.COUNT_STORAGE_GROUP, ((CountOperator)
operator).getPath());
case SQLConstant.TOK_COUNT_NODE_TIMESERIES:
- return new CountPlan(
- ShowContentType.COUNT_NODE_TIMESERIES,
- ((CountOperator) operator).getPath(),
- ((CountOperator) operator).getLevel());
+ return new CountPlan(ShowContentType.COUNT_NODE_TIMESERIES,
+ ((CountOperator) operator).getPath(), ((CountOperator)
operator).getLevel());
case SQLConstant.TOK_COUNT_NODES:
- return new CountPlan(
- ShowContentType.COUNT_NODES,
- ((CountOperator) operator).getPath(),
+ return new CountPlan(ShowContentType.COUNT_NODES, ((CountOperator)
operator).getPath(),
((CountOperator) operator).getLevel());
case SQLConstant.TOK_COUNT_TIMESERIES:
return new CountPlan(
@@ -329,8 +327,10 @@ public class PhysicalGenerator {
return SchemaUtils.getSeriesTypesByPath(paths);
}
+
@SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity
warning
- private PhysicalPlan transformQuery(QueryOperator queryOperator) throws
QueryProcessException {
+ private PhysicalPlan transformQuery(QueryOperator queryOperator, int
fetchSize)
+ throws QueryProcessException {
QueryPlan queryPlan;
if (queryOperator.hasAggregation()) {
@@ -539,6 +539,13 @@ public class PhysicalGenerator {
measurements = slimitTrimColumn(measurements, seriesSlimit,
seriesOffset);
}
+ int maxDeduplicatedPathNum = QueryResourceManager.getInstance()
+ .getMaxDeduplicatedPathNum(fetchSize);
+
+ if (measurements.size() > maxDeduplicatedPathNum) {
+ throw new PathNumOverLimitException(maxDeduplicatedPathNum,
measurements.size());
+ }
+
// assigns to alignByDevicePlan
alignByDevicePlan.setMeasurements(measurements);
alignByDevicePlan.setMeasurementAliasMap(measurementAliasMap);
@@ -584,7 +591,7 @@ public class PhysicalGenerator {
}
}
try {
- deduplicate(queryPlan);
+ deduplicate(queryPlan, fetchSize);
} catch (MetadataException e) {
throw new QueryProcessException(e);
}
@@ -662,7 +669,8 @@ public class PhysicalGenerator {
}
@SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity
warning
- private void deduplicate(QueryPlan queryPlan) throws MetadataException {
+ private void deduplicate(QueryPlan queryPlan, int fetchSize)
+ throws MetadataException, PathNumOverLimitException {
// generate dataType first
List<PartialPath> paths = queryPlan.getPaths();
List<TSDataType> dataTypes = getSeriesTypes(paths);
@@ -700,6 +708,9 @@ public class PhysicalGenerator {
}
indexedPaths.sort(Comparator.comparing(pair -> pair.left));
+ int maxDeduplicatedPathNum = QueryResourceManager.getInstance()
+ .getMaxDeduplicatedPathNum(fetchSize);
+ int deduplicatedPathNum = 0;
int index = 0;
for (Pair<PartialPath, Integer> indexedPath : indexedPaths) {
String column = indexedPath.left.getTsAlias();
@@ -714,6 +725,10 @@ public class PhysicalGenerator {
TSDataType seriesType = dataTypes.get(indexedPath.right);
rawDataQueryPlan.addDeduplicatedPaths(indexedPath.left);
rawDataQueryPlan.addDeduplicatedDataTypes(seriesType);
+ deduplicatedPathNum++;
+ if (deduplicatedPathNum > maxDeduplicatedPathNum) {
+ throw new PathNumOverLimitException(maxDeduplicatedPathNum,
deduplicatedPathNum);
+ }
columnSet.add(column);
rawDataQueryPlan.addPathToIndex(column, index++);
if (queryPlan instanceof AggregationPlan) {
diff --git
a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
index b8048fc..5d089a6 100644
---
a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
+++
b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Set;
import org.apache.iotdb.db.exception.metadata.MetadataException;
import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
+import org.apache.iotdb.db.exception.query.PathNumOverLimitException;
import org.apache.iotdb.db.exception.runtime.SQLParserException;
import org.apache.iotdb.db.metadata.PartialPath;
import org.apache.iotdb.db.qp.constant.SQLConstant;
@@ -36,6 +37,7 @@ import org.apache.iotdb.db.qp.logical.crud.QueryOperator;
import org.apache.iotdb.db.qp.logical.crud.SFWOperator;
import org.apache.iotdb.db.qp.logical.crud.SelectOperator;
import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.tsfile.utils.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,7 +53,8 @@ public class ConcatPathOptimizer implements ILogicalOptimizer
{
@SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity
warning
@Override
- public Operator transform(Operator operator) throws LogicalOptimizeException
{
+ public Operator transform(Operator operator, int maxDeduplicatedPathNum)
+ throws LogicalOptimizeException, PathNumOverLimitException {
if (!(operator instanceof SFWOperator)) {
logger.warn("given operator isn't SFWOperator, cannot concat
seriesPath");
return operator;
@@ -88,12 +91,21 @@ public class ConcatPathOptimizer implements
ILogicalOptimizer {
if (operator instanceof QueryOperator) {
if (!((QueryOperator) operator).isAlignByDevice() || ((QueryOperator)
operator)
.isLastQuery()) {
- concatSelect(prefixPaths, select); // concat and remove star
+ // concat and remove star
if (((QueryOperator) operator).hasSlimit()) {
int seriesLimit = ((QueryOperator) operator).getSeriesLimit();
int seriesOffset = ((QueryOperator) operator).getSeriesOffset();
- slimitTrim(select, seriesLimit, seriesOffset);
+ if (seriesLimit > maxDeduplicatedPathNum) {
+ throw new PathNumOverLimitException(maxDeduplicatedPathNum,
seriesLimit);
+ }
+ concatSelect(prefixPaths, select, seriesLimit, seriesOffset);
+ slimitTrim(select, seriesOffset);
+ } else {
+ concatSelect(prefixPaths, select, maxDeduplicatedPathNum + 1, 0);
+ if (select.getSuffixPaths().size() > maxDeduplicatedPathNum) {
+ throw new PathNumOverLimitException(maxDeduplicatedPathNum);
+ }
}
} else {
isAlignByDevice = true;
@@ -159,7 +171,7 @@ public class ConcatPathOptimizer implements
ILogicalOptimizer {
* Extract paths from select&from cql, expand them into complete versions,
and reassign them to
* selectOperator's suffixPathList. Treat aggregations similarly.
*/
- private void concatSelect(List<PartialPath> fromPaths, SelectOperator
selectOperator)
+ private void concatSelect(List<PartialPath> fromPaths, SelectOperator
selectOperator, int limit, int offset)
throws LogicalOptimizeException {
List<PartialPath> suffixPaths = judgeSelectOperator(selectOperator);
@@ -180,34 +192,26 @@ public class ConcatPathOptimizer implements
ILogicalOptimizer {
}
}
- removeStarsInPath(allPaths, afterConcatAggregations, selectOperator);
+ removeStarsInPath(allPaths, afterConcatAggregations, selectOperator,
limit, offset);
}
/**
- * Make 'SLIMIT&SOFFSET' take effect by trimming the suffixList and
aggregations of the
+ * Make 'SOFFSET' take effect by trimming the suffixList and aggregations of
the
* selectOperator.
*
- * @param seriesLimit is ensured to be positive integer
* @param seriesOffset is ensured to be non-negative integer
*/
- private void slimitTrim(SelectOperator select, int seriesLimit, int
seriesOffset)
+ private void slimitTrim(SelectOperator select, int seriesOffset)
throws LogicalOptimizeException {
List<PartialPath> suffixList = select.getSuffixPaths();
List<String> aggregations = select.getAggregations();
int size = suffixList.size();
// check parameter range
- if (seriesOffset >= size) {
+ if (size == 0) {
throw new LogicalOptimizeException("SOFFSET <SOFFSETValue>: SOFFSETValue
exceeds the range.");
}
- int endPosition = seriesOffset + seriesLimit;
- if (endPosition > size) {
- endPosition = size;
- }
-
- // trim seriesPath list
- List<PartialPath> trimedSuffixList = new
ArrayList<>(suffixList.subList(seriesOffset, endPosition));
- select.setSuffixPathList(trimedSuffixList);
+ int endPosition = seriesOffset + size;
// trim aggregations if exists
if (aggregations != null && !aggregations.isEmpty()) {
@@ -287,7 +291,7 @@ public class ConcatPathOptimizer implements
ILogicalOptimizer {
HashSet<PartialPath> pathSet = new HashSet<>();
try {
for (PartialPath path : paths) {
- List<PartialPath> all = removeWildcard(path);
+ List<PartialPath> all = removeWildcard(path, 0, 0).left;
for (PartialPath subPath : all) {
if (!pathSet.contains(subPath)) {
pathSet.add(subPath);
@@ -302,12 +306,14 @@ public class ConcatPathOptimizer implements
ILogicalOptimizer {
}
private void removeStarsInPath(List<PartialPath> paths, List<String>
afterConcatAggregations,
- SelectOperator selectOperator) throws LogicalOptimizeException {
+ SelectOperator selectOperator, int limit, int offset) throws
LogicalOptimizeException {
List<PartialPath> retPaths = new ArrayList<>();
List<String> newAggregations = new ArrayList<>();
for (int i = 0; i < paths.size(); i++) {
try {
- List<PartialPath> actualPaths = removeWildcard(paths.get(i));
+ Pair<List<PartialPath>, Integer> pair = removeWildcard(paths.get(i),
limit, offset);
+ List<PartialPath> actualPaths = pair.left;
+ offset = offset - pair.right;
if (paths.get(i).getTsAlias() != null) {
if (actualPaths.size() == 1) {
actualPaths.get(0).setTsAlias(paths.get(i).getTsAlias());
@@ -330,7 +336,7 @@ public class ConcatPathOptimizer implements
ILogicalOptimizer {
selectOperator.setAggregations(newAggregations);
}
- protected List<PartialPath> removeWildcard(PartialPath path) throws
MetadataException {
- return IoTDB.metaManager.getAllTimeseriesPathWithAlias(path);
+ protected Pair<List<PartialPath>, Integer> removeWildcard(PartialPath path,
int limit, int offset) throws MetadataException {
+ return IoTDB.metaManager.getAllTimeseriesPathWithAlias(path, limit,
offset);
}
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ILogicalOptimizer.java
b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ILogicalOptimizer.java
index bd542d6..4467a8a 100644
---
a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ILogicalOptimizer.java
+++
b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ILogicalOptimizer.java
@@ -19,6 +19,7 @@
package org.apache.iotdb.db.qp.strategy.optimizer;
import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
+import org.apache.iotdb.db.exception.query.PathNumOverLimitException;
import org.apache.iotdb.db.qp.logical.Operator;
/**
@@ -27,5 +28,6 @@ import org.apache.iotdb.db.qp.logical.Operator;
@FunctionalInterface
public interface ILogicalOptimizer {
- Operator transform(Operator operator) throws LogicalOptimizeException;
+ Operator transform(Operator operator, int maxDeduplicatedPathNum)
+ throws LogicalOptimizeException, PathNumOverLimitException;
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/query/control/QueryResourceManager.java
b/server/src/main/java/org/apache/iotdb/db/query/control/QueryResourceManager.java
index 8aaa311..7d14885 100644
---
a/server/src/main/java/org/apache/iotdb/db/query/control/QueryResourceManager.java
+++
b/server/src/main/java/org/apache/iotdb/db/query/control/QueryResourceManager.java
@@ -18,6 +18,7 @@
*/
package org.apache.iotdb.db.query.control;
+
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -43,6 +44,7 @@ import org.apache.iotdb.tsfile.read.filter.basic.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
/**
* <p>
* QueryResourceManager manages resource (file streams) used by each query
job, and assign Ids to
@@ -53,8 +55,8 @@ import org.slf4j.LoggerFactory;
*/
public class QueryResourceManager {
- private AtomicLong queryIdAtom = new AtomicLong();
- private QueryFileManager filePathsManager;
+ private final AtomicLong queryIdAtom = new AtomicLong();
+ private final QueryFileManager filePathsManager;
private static final Logger logger =
LoggerFactory.getLogger(QueryResourceManager.class);
// record the total number and size of chunks for each query id
private Map<Long, Integer> chunkNumMap = new ConcurrentHashMap<>();
@@ -64,29 +66,58 @@ public class QueryResourceManager {
private Map<Long, Set<TsFileResource>> seqFileNumMap = new
ConcurrentHashMap<>();
private Map<Long, Set<TsFileResource>> unseqFileNumMap = new
ConcurrentHashMap<>();
private IoTDBConfig config = IoTDBDescriptor.getInstance().getConfig();
+
/**
* Record temporary files used for external sorting.
* <p>
* Key: query job id. Value: temporary file list used for external sorting.
*/
- private Map<Long, List<IExternalSortFileDeserializer>> externalSortFileMap;
+ private final Map<Long, List<IExternalSortFileDeserializer>>
externalSortFileMap;
+
+ private final Map<Long, Long> queryIdEstimatedMemoryMap;
+
+ // current total free memory for reading process(not including the cache
memory)
+ private final AtomicLong totalFreeMemoryForRead;
+
+ // estimated size for one point memory size, the unit is byte
+ private static final long POINT_ESTIMATED_SIZE = 16L;
+
+ private static final IoTDBConfig CONFIG =
IoTDBDescriptor.getInstance().getConfig();
private QueryResourceManager() {
filePathsManager = new QueryFileManager();
externalSortFileMap = new ConcurrentHashMap<>();
+ queryIdEstimatedMemoryMap = new ConcurrentHashMap<>();
+ totalFreeMemoryForRead = new AtomicLong(
+
IoTDBDescriptor.getInstance().getConfig().getAllocateMemoryForReadWithoutCache());
}
public static QueryResourceManager getInstance() {
return QueryTokenManagerHelper.INSTANCE;
}
+ public int getMaxDeduplicatedPathNum(int fetchSize) {
+ return Math.min((int) ((totalFreeMemoryForRead.get() / fetchSize) /
POINT_ESTIMATED_SIZE),
+ CONFIG.getMaxQueryDeduplicatedPathNum());
+ }
+
/**
* Register a new query. When a query request is created firstly, this
method must be invoked.
*/
- public long assignQueryId(boolean isDataQuery) {
+ public long assignQueryId(boolean isDataQuery, int fetchSize, int
deduplicatedPathNum) {
long queryId = queryIdAtom.incrementAndGet();
if (isDataQuery) {
filePathsManager.addQueryId(queryId);
+ if (deduplicatedPathNum > 0) {
+ long estimatedMemoryUsage =
+ (long) deduplicatedPathNum * POINT_ESTIMATED_SIZE * (long)
fetchSize;
+ // apply the memory successfully
+ if (totalFreeMemoryForRead.addAndGet(-estimatedMemoryUsage) >= 0) {
+ queryIdEstimatedMemoryMap.put(queryId, estimatedMemoryUsage);
+ } else {
+ totalFreeMemoryForRead.addAndGet(estimatedMemoryUsage);
+ }
+ }
}
return queryId;
}
@@ -138,7 +169,8 @@ public class QueryResourceManager {
if (config.isEnablePerformanceTracing()) {
boolean isprinted = false;
if (seqFileNumMap.get(queryId) != null && unseqFileNumMap.get(queryId)
!= null) {
- TracingManager.getInstance().writeTsFileInfo(queryId,
seqFileNumMap.remove(queryId).size(),
+ TracingManager.getInstance()
+ .writeTsFileInfo(queryId, seqFileNumMap.remove(queryId).size(),
unseqFileNumMap.remove(queryId).size());
isprinted = true;
}
@@ -167,6 +199,13 @@ public class QueryResourceManager {
}
externalSortFileMap.remove(queryId);
}
+
+ // put back the memory usage
+ Long estimatedMemoryUsage = queryIdEstimatedMemoryMap.remove(queryId);
+ if (estimatedMemoryUsage != null) {
+ totalFreeMemoryForRead.addAndGet(estimatedMemoryUsage);
+ }
+
// remove usage of opened file paths of current thread
filePathsManager.removeUsedFilesForQuery(queryId);
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
b/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
index 8444949..76ad37d 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
@@ -68,6 +68,7 @@ import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
import org.apache.iotdb.db.qp.physical.crud.InsertTabletPlan;
import org.apache.iotdb.db.qp.physical.crud.LastQueryPlan;
import org.apache.iotdb.db.qp.physical.crud.QueryPlan;
+import org.apache.iotdb.db.qp.physical.crud.RawDataQueryPlan;
import org.apache.iotdb.db.qp.physical.sys.AuthorPlan;
import org.apache.iotdb.db.qp.physical.sys.CreateMultiTimeSeriesPlan;
import org.apache.iotdb.db.qp.physical.sys.CreateTimeSeriesPlan;
@@ -144,7 +145,7 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
private static final int MAX_SIZE =
IoTDBDescriptor.getInstance().getConfig().getQueryCacheSizeInMetric();
private static final int DELETE_SIZE = 20;
- private static final int FETCH_SIZE = 10000;
+ private static final int DEFAULT_FETCH_SIZE = 10000;
private static final String ERROR_PARSING_SQL =
"meet error while parsing SQL to physical plan: {}";
private static final String SERVER_INTERNAL_ERROR = "{}: server Internal
Error: ";
@@ -354,8 +355,10 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
status = RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS);
break;
case "ALL_COLUMNS":
- resp.setColumnsList(getPaths(new
PartialPath(req.getColumnPath())).stream().map(PartialPath::getFullPath).collect(
- Collectors.toList()));
+ resp.setColumnsList(
+ getPaths(new
PartialPath(req.getColumnPath())).stream().map(PartialPath::getFullPath)
+ .collect(
+ Collectors.toList()));
status = RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS);
break;
default:
@@ -425,8 +428,8 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
// on finding queries in a batch, such query will be ignored and an error
will be generated
private boolean executeStatementInBatch(String statement, List<TSStatus>
result, long sessionId) {
try {
- PhysicalPlan physicalPlan =
- processor.parseSQLToPhysicalPlan(statement,
sessionIdZoneIdMap.get(sessionId));
+ PhysicalPlan physicalPlan = processor
+ .parseSQLToPhysicalPlan(statement,
sessionIdZoneIdMap.get(sessionId), DEFAULT_FETCH_SIZE);
if (physicalPlan.isQuery()) {
throw new QueryInBatchStatementException(statement);
}
@@ -478,8 +481,9 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
}
String statement = req.getStatement();
- PhysicalPlan physicalPlan =
- processor.parseSQLToPhysicalPlan(statement,
sessionIdZoneIdMap.get(req.getSessionId()));
+ PhysicalPlan physicalPlan = processor
+ .parseSQLToPhysicalPlan(statement,
sessionIdZoneIdMap.get(req.getSessionId()),
+ req.fetchSize);
if (physicalPlan.isQuery()) {
return internalExecuteQueryStatement(statement, req.statementId,
physicalPlan,
req.fetchSize,
@@ -516,8 +520,9 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
String statement = req.getStatement();
PhysicalPlan physicalPlan;
try {
- physicalPlan =
- processor.parseSQLToPhysicalPlan(statement,
sessionIdZoneIdMap.get(req.getSessionId()));
+ physicalPlan = processor
+ .parseSQLToPhysicalPlan(statement,
sessionIdZoneIdMap.get(req.getSessionId()),
+ req.fetchSize);
} catch (QueryProcessException | SQLParserException e) {
logger.info(ERROR_PARSING_SQL, e.getMessage());
return
RpcUtils.getTSExecuteStatementResp(TSStatusCode.SQL_PARSE_ERROR,
e.getMessage());
@@ -601,7 +606,7 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
// In case users forget to set this field in query, use the default value
if (fetchSize == 0) {
- fetchSize = FETCH_SIZE;
+ fetchSize = DEFAULT_FETCH_SIZE;
}
if (plan instanceof ShowTimeSeriesPlan) {
@@ -628,8 +633,20 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
resp.setIgnoreTimeStamp(true);
} // else default ignoreTimeStamp is false
resp.setOperationType(plan.getOperatorType().toString());
+
+ // get deduplicated path num
+ int deduplicatedPathNum = -1;
+ if (plan instanceof AlignByDevicePlan) {
+ deduplicatedPathNum = ((AlignByDevicePlan)
plan).getMeasurements().size();
+ } else if (plan instanceof LastQueryPlan) {
+ deduplicatedPathNum = 0;
+ } else if (plan instanceof RawDataQueryPlan) {
+ deduplicatedPathNum = ((RawDataQueryPlan)
plan).getDeduplicatedPaths().size();
+ }
+
// generate the queryId for the operation
- queryId = generateQueryId(true);
+
+ queryId = generateQueryId(true, fetchSize, deduplicatedPathNum);
if (plan instanceof QueryPlan && config.isEnablePerformanceTracing()) {
if (!(plan instanceof AlignByDevicePlan)) {
TracingManager.getInstance().writeQueryInfo(queryId, statement,
plan.getPaths().size());
@@ -825,7 +842,8 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
for (PartialPath path : paths) {
String column = path.getTsAlias();
if (column == null) {
- column = path.getMeasurementAlias() != null ?
path.getFullPathWithAlias() : path.getFullPath();
+ column = path.getMeasurementAlias() != null ?
path.getFullPathWithAlias()
+ : path.getFullPath();
}
respColumns.add(column);
seriesTypes.add(getSeriesTypeByPath(path));
@@ -1068,7 +1086,7 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
status = executeNonQueryPlan(plan);
TSExecuteStatementResp resp = RpcUtils.getTSExecuteStatementResp(status);
- long queryId = generateQueryId(false);
+ long queryId = generateQueryId(false, DEFAULT_FETCH_SIZE, -1);
resp.setQueryId(queryId);
return resp;
}
@@ -1086,7 +1104,8 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
PhysicalPlan physicalPlan;
try {
- physicalPlan = processor.parseSQLToPhysicalPlan(statement,
sessionIdZoneIdMap.get(sessionId));
+ physicalPlan = processor
+ .parseSQLToPhysicalPlan(statement,
sessionIdZoneIdMap.get(sessionId), DEFAULT_FETCH_SIZE);
} catch (QueryProcessException | SQLParserException e) {
logger.warn(ERROR_PARSING_SQL, statement, e);
return RpcUtils.getTSExecuteStatementResp(TSStatusCode.SQL_PARSE_ERROR,
e.getMessage());
@@ -1381,7 +1400,8 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
return RpcUtils.getStatus(TSStatusCode.NOT_LOGIN_ERROR);
}
- InsertTabletPlan insertTabletPlan = new InsertTabletPlan(new
PartialPath(req.deviceId), req.measurements);
+ InsertTabletPlan insertTabletPlan = new InsertTabletPlan(new
PartialPath(req.deviceId),
+ req.measurements);
insertTabletPlan.setTimes(QueryDataSetUtils.readTimesFromBuffer(req.timestamps,
req.size));
insertTabletPlan.setColumns(
QueryDataSetUtils.readValuesFromBuffer(
@@ -1415,7 +1435,8 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
List<TSStatus> statusList = new ArrayList<>();
for (int i = 0; i < req.deviceIds.size(); i++) {
- InsertTabletPlan insertTabletPlan = new InsertTabletPlan(new
PartialPath(req.deviceIds.get(i)),
+ InsertTabletPlan insertTabletPlan = new InsertTabletPlan(
+ new PartialPath(req.deviceIds.get(i)),
req.measurementsList.get(i));
insertTabletPlan.setTimes(
QueryDataSetUtils.readTimesFromBuffer(req.timestampsList.get(i),
req.sizeList.get(i)));
@@ -1689,11 +1710,14 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
: RpcUtils.getStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR);
}
- private long generateQueryId(boolean isDataQuery) {
- return QueryResourceManager.getInstance().assignQueryId(isDataQuery);
+
+ private long generateQueryId(boolean isDataQuery, int fetchSize, int
deduplicatedPathNum) {
+ return QueryResourceManager.getInstance()
+ .assignQueryId(isDataQuery, fetchSize, deduplicatedPathNum);
}
- protected List<TSDataType> getSeriesTypesByPaths(List<PartialPath> paths,
List<String> aggregations)
+ protected List<TSDataType> getSeriesTypesByPaths(List<PartialPath> paths,
+ List<String> aggregations)
throws MetadataException {
return SchemaUtils.getSeriesTypesByPaths(paths, aggregations);
}
diff --git
a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSequenceDataQueryIT.java
b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSequenceDataQueryIT.java
index 8f8c82b..415fae6 100644
---
a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSequenceDataQueryIT.java
+++
b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSequenceDataQueryIT.java
@@ -185,7 +185,8 @@ public class IoTDBSequenceDataQueryIT {
pathList.add(new PartialPath(TestConstant.d1 +
TsFileConstant.PATH_SEPARATOR + TestConstant.s1));
dataTypes.add(TSDataType.INT64);
- TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true);
+ TEST_QUERY_JOB_ID = QueryResourceManager.getInstance()
+ .assignQueryId(true, 1024, pathList.size());
TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID);
RawDataQueryPlan queryPlan = new RawDataQueryPlan();
queryPlan.setDeduplicatedDataTypes(dataTypes);
@@ -216,7 +217,8 @@ public class IoTDBSequenceDataQueryIT {
dataTypes.add(TSDataType.INT64);
GlobalTimeExpression globalTimeExpression = new
GlobalTimeExpression(TimeFilter.gtEq(800L));
- TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true);
+ TEST_QUERY_JOB_ID = QueryResourceManager.getInstance()
+ .assignQueryId(true, 1024, pathList.size());
TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID);
RawDataQueryPlan queryPlan = new RawDataQueryPlan();
@@ -264,7 +266,8 @@ public class IoTDBSequenceDataQueryIT {
SingleSeriesExpression singleSeriesExpression = new
SingleSeriesExpression(queryPath,
ValueFilter.gtEq(14));
- TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true);
+ TEST_QUERY_JOB_ID = QueryResourceManager.getInstance()
+ .assignQueryId(true, 1024, pathList.size());
TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID);
RawDataQueryPlan queryPlan = new RawDataQueryPlan();
diff --git
a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSeriesReaderIT.java
b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSeriesReaderIT.java
index 54bba5f..a5304df 100644
---
a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSeriesReaderIT.java
+++
b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSeriesReaderIT.java
@@ -278,7 +278,8 @@ public class IoTDBSeriesReaderIT {
pathList.add(new PartialPath(TestConstant.d1 +
TsFileConstant.PATH_SEPARATOR + TestConstant.s1));
dataTypes.add(TSDataType.INT64);
- TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true);
+ TEST_QUERY_JOB_ID = QueryResourceManager.getInstance()
+ .assignQueryId(true, 1024, pathList.size());
TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID);
RawDataQueryPlan queryPlan = new RawDataQueryPlan();
@@ -308,7 +309,8 @@ public class IoTDBSeriesReaderIT {
SingleSeriesExpression singleSeriesExpression = new
SingleSeriesExpression(p,
ValueFilter.gtEq(20));
- TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true);
+ TEST_QUERY_JOB_ID = QueryResourceManager.getInstance()
+ .assignQueryId(true, 1024, pathList.size());
TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID);
RawDataQueryPlan queryPlan = new RawDataQueryPlan();
@@ -335,7 +337,7 @@ public class IoTDBSeriesReaderIT {
List<TSDataType> dataTypes = Collections.singletonList(TSDataType.INT32);
SingleSeriesExpression expression = new SingleSeriesExpression(path,
TimeFilter.gt(22987L));
- TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true);
+ TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true,
1024, 1);
TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID);
RawDataQueryPlan queryPlan = new RawDataQueryPlan();
@@ -373,7 +375,8 @@ public class IoTDBSeriesReaderIT {
dataTypes.add(TSDataType.INT64);
queryPlan.setDeduplicatedDataTypes(dataTypes);
- TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true);
+ TEST_QUERY_JOB_ID = QueryResourceManager.getInstance()
+ .assignQueryId(true, 1024, pathList.size());
TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID);
SingleSeriesExpression singleSeriesExpression = new
SingleSeriesExpression(path1,
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
b/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
index bab01f1..86a4901 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
@@ -185,14 +185,14 @@ public class MTreeTest {
assertEquals("root.a.d1.s0", result.get(1).getFullPath());
List<PartialPath> result2 = root
- .getAllTimeseriesPathWithAlias(new PartialPath("root.a.*.s0"));
+ .getAllTimeseriesPathWithAlias(new PartialPath("root.a.*.s0"), 0,
0).left;
assertEquals(2, result2.size());
assertEquals("root.a.d0.s0", result2.get(0).getFullPath());
assertNull(result2.get(0).getMeasurementAlias());
assertEquals("root.a.d1.s0", result2.get(1).getFullPath());
assertNull(result2.get(1).getMeasurementAlias());
- result2 = root.getAllTimeseriesPathWithAlias(new
PartialPath("root.a.*.temperature"));
+ result2 = root.getAllTimeseriesPathWithAlias(new
PartialPath("root.a.*.temperature"), 0, 0).left;
assertEquals(2, result2.size());
assertEquals("root.a.d0.temperature",
result2.get(0).getFullPathWithAlias());
assertEquals("root.a.d1.temperature",
result2.get(1).getFullPathWithAlias());
@@ -464,7 +464,7 @@ public class MTreeTest {
assertEquals(2, root.getDevices(new PartialPath("root")).size());
assertEquals(2, root.getAllTimeseriesCount(new PartialPath("root")));
assertEquals(2, root.getAllTimeseriesPath(new PartialPath("root")).size());
- assertEquals(2, root.getAllTimeseriesPathWithAlias(new
PartialPath("root")).size());
+ assertEquals(2, root.getAllTimeseriesPathWithAlias(new
PartialPath("root"), 0, 0).left.size());
}
@Test
diff --git
a/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java
b/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java
index f44567e..c68eea7 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java
@@ -182,7 +182,7 @@ public class LogicalPlanSmallTest {
.parse(sqlStr, IoTDBDescriptor.getInstance().getConfig().getZoneID());
IoTDB.metaManager.init();
ConcatPathOptimizer concatPathOptimizer = new ConcatPathOptimizer();
- concatPathOptimizer.transform(operator);
+ concatPathOptimizer.transform(operator, 1000);
IoTDB.metaManager.clear();
// expected to throw LogicalOptimizeException: SOFFSET <SOFFSETValue>:
SOFFSETValue exceeds the range.
}
diff --git
a/server/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
b/server/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
index 4877a32..a9222a8 100644
--- a/server/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
+++ b/server/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
@@ -103,11 +103,11 @@ public class EnvironmentUtils {
}
//try jmx connection
try {
- JMXServiceURL url =
- new
JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:31999/jmxrmi");
- JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
+ JMXServiceURL url =
+ new
JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:31999/jmxrmi");
+ JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
logger.error("stop JMX failed. 31999 can be connected now.");
- jmxConnector.close();
+ jmxConnector.close();
} catch (IOException e) {
//do nothing
}
@@ -130,7 +130,6 @@ public class EnvironmentUtils {
IoTDBDescriptor.getInstance().getConfig().setReadOnly(false);
-
// clean cache
if (config.isMetaDataCacheEnable()) {
ChunkMetadataCache.getInstance().clear();
@@ -206,12 +205,12 @@ public class EnvironmentUtils {
createAllDir();
// disable the system monitor
config.setEnableStatMonitor(false);
- TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true);
+ TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true,
1024, 0);
TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID);
}
public static void stopDaemon() {
- if(daemon != null) {
+ if (daemon != null) {
daemon.stop();
}
}
@@ -223,7 +222,7 @@ public class EnvironmentUtils {
}
public static void activeDaemon() {
- if(daemon != null) {
+ if (daemon != null) {
daemon.active();
}
}
diff --git
a/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
b/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
index 75bca6c..f54c6af 100644
---
a/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
+++
b/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
@@ -57,6 +57,7 @@ import java.util.Locale;
* </p>
*/
public class EnvironmentUtils {
+
private static String[] creationSqls = new String[]{
"SET STORAGE GROUP TO root.vehicle.d0",
"SET STORAGE GROUP TO root.vehicle.d1",
@@ -92,7 +93,8 @@ public class EnvironmentUtils {
private static IoTDBConfig config =
IoTDBDescriptor.getInstance().getConfig();
private static DirectoryManager directoryManager =
DirectoryManager.getInstance();
- public static long TEST_QUERY_JOB_ID =
QueryResourceManager.getInstance().assignQueryId(true);
+ public static long TEST_QUERY_JOB_ID = QueryResourceManager.getInstance()
+ .assignQueryId(true, 1024, 0);
public static QueryContext TEST_QUERY_CONTEXT = new
QueryContext(TEST_QUERY_JOB_ID);
private static long oldTsFileThreshold = config.getTsFileSizeThreshold();
@@ -159,16 +161,14 @@ public class EnvironmentUtils {
}
/**
- * disable the system monitor</br>
- * this function should be called before all code in the setup
+ * disable the system monitor</br> this function should be called before all
code in the setup
*/
public static void closeStatMonitor() {
config.setEnableStatMonitor(false);
}
/**
- * disable memory control</br>
- * this function should be called before all code in the setup
+ * disable memory control</br> this function should be called before all
code in the setup
*/
public static void envSetUp() throws StartupException, IOException {
IoTDBDescriptor.getInstance().getConfig().setEnableParameterAdapter(false);
@@ -192,7 +192,7 @@ public class EnvironmentUtils {
StorageEngine.getInstance().reset();
MultiFileLogNodeManager.getInstance().start();
FlushManager.getInstance().start();
- TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true);
+ TEST_QUERY_JOB_ID = QueryResourceManager.getInstance().assignQueryId(true,
1024, 0);
TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID);
}
@@ -210,7 +210,7 @@ public class EnvironmentUtils {
// create wal
createDir(config.getWalDir());
// create data
- for (String dataDir: config.getDataDirs()) {
+ for (String dataDir : config.getDataDirs()) {
createDir(dataDir);
}
}