iotdb
iotdb copied to clipboard
创建大量time series时,客户端show timeseries导致服务挂掉
机器IP:192.168.10.57
创建了600多万个time series,打开客户端输入show timeseries后卡住,ctrl C强退出客户端后服务disappear
iotdb版本不是最新的,不过最新版的iotdb可能也存在这个问题, 准备用最新版的iotdb试一下看看
1. 卡住应该是因为java.lang.OutOfMemoryError with StringBuilder or StringBuffer
"The problem with StringBuilder I see is it doubles the capacity from current length. Lets say the internal char buffer length is 65000 and more 100 chars has to be added, then the buffer capacity is doubled to 65000 * 2. If we dive into the code of Arrays.copyOf() method line no# 2882. It tries to create a new char[] of size 65000 * 2 (in our case). And this will throw Error if the Java Virtual machine does not have enough to allocate."
可以修改增大iotdb-env文件中关于heap size的设置试试。
首先明确“show timeseries”命令只支持在sql中使用(这没问题),其次“show timeseries"的实现核心是MTree类的MNodeToString函数,该函数使用递归来给StringBuilder.append直到遍历完这棵树的信息。 用如下测试代码简单模拟这一核心步骤:
public void test() { MTree root = new MTree("root"); String format = "root.laptop.d1.s%d"; for(int i =0;i<6000000;i++) { try { root.addTimeseriesPath(String.format(format,i), "INT32", "RLE", new String[0]); } catch (PathErrorException e) { e.printStackTrace(); fail(e.getMessage()); } } System.out.println(root.toString()); }
结果报错:
java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.AbstractStringBuilder.
2. 也可以使用show timeseries <path>查询
注:该功能目前在iotdb的STS2分支上,可以sql也可以在jdbc中调用。 它的实现逻辑是先把查询给定的一个path解析为完整的路径集,然后遍历每一条完整路径对应的叶子节点,取得其[name,storage group,dataType,encoding]信息,组装到List<String> tsRow中。最终一次性返回show timeseries path的全部结果。path可以是一个完整的路径,或者带星路径,或者前缀路径。 代码简要如下:
List<String> paths = MManager.getInstance().getPaths(path); ...... for (int i = 0; i < paths.size(); i++) { String apath = paths.get(i); List<String> tsRow = new ArrayList<>(); tsRow.add(apath); MNode leafNode = MManager.getInstance().getNodeByPath(apath); if (leafNode.isLeaf()) { // get [name,storage group,dataType,encoding] ColumnSchema columnSchema = leafNode.getSchema(); tsRow.add(leafNode.getDataFileName()); tsRow.add(columnSchema.dataType.toString()); tsRow.add(columnSchema.encoding.toString()); } showTimeseriesList.add(tsRow); }
不过当timeseries特别多的时候,也可能发生outOfMemory,只不过ArrayList发生outOfMemory的阈值可能比StringBuffer的高一点。
