blob: 5174dad3160689f74e7e96f98eed87699c097026 [file] [log] [blame]
(window.webpackJsonp=window.webpackJsonp||[]).push([[285],{846:function(e,a,t){"use strict";t.r(a);var s=t(68),n=Object(s.a)({},(function(){var e=this,a=e.$createElement,t=e._self._c||a;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"聚合查询"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#聚合查询"}},[e._v("#")]),e._v(" 聚合查询")]),e._v(" "),t("p",[e._v("聚合查询的主要逻辑在 AggregateExecutor")]),e._v(" "),t("ul",[t("li",[e._v("org.apache.iotdb.db.query.executor.AggregationExecutor")])]),e._v(" "),t("h2",{attrs:{id:"不带值过滤条件的聚合查询"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#不带值过滤条件的聚合查询"}},[e._v("#")]),e._v(" 不带值过滤条件的聚合查询")]),e._v(" "),t("p",[e._v("对于不带值过滤条件的聚合查询,通过 "),t("code",[e._v("executeWithoutValueFilter()")]),e._v(" 方法获得结果并构建 dataSet。首先使用 "),t("code",[e._v("mergeSameSeries()")]),e._v(" 方法将对于相同时间序列的聚合查询合并,例如:如果需要计算count(s1), sum(s2), count(s3), sum(s1),即需要计算s1的两个聚合值,那么将会得到pathToAggrIndexesMap结果为:s1 -> 0, 3; s2 -> 1; s3 -> 2。")]),e._v(" "),t("p",[e._v("那么将会得到 "),t("code",[e._v("pathToAggrIndexesMap")]),e._v(",其中每一个 entry 都是一个 series 的聚合查询,因此可以通过调用 "),t("code",[e._v("groupAggregationsBySeries()")]),e._v(" 方法计算出其聚合值 "),t("code",[e._v("aggregateResults")]),e._v("。在最后创建结果集之前,需要将其顺序还原为用户查询的顺序。最后使用 "),t("code",[e._v("constructDataSet()")]),e._v(" 方法创建结果集并返回。")]),e._v(" "),t("p",[e._v("下面详细讲解 "),t("code",[e._v("groupAggregationsBySeries()")]),e._v(" 方法。首先创建一个 "),t("code",[e._v("IAggregateReader")]),e._v(":")]),e._v(" "),t("div",{staticClass:"language- line-numbers-mode"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("IAggregateReader seriesReader = new SeriesAggregateReader(\n pathToAggrIndexes.getKey(), tsDataType, context, QueryResourceManager.getInstance()\n .getQueryDataSource(seriesPath, context, timeFilter), timeFilter, null);\n")])]),e._v(" "),t("div",{staticClass:"line-numbers-wrapper"},[t("span",{staticClass:"line-number"},[e._v("1")]),t("br"),t("span",{staticClass:"line-number"},[e._v("2")]),t("br"),t("span",{staticClass:"line-number"},[e._v("3")]),t("br")])]),t("p",[e._v("对于每一个 entry(即series),首先为其每一种聚合查询创建一个聚合结果 "),t("code",[e._v("AggregateResult")]),e._v(",同时维护一个布尔值列表 "),t("code",[e._v("isCalculatedList")]),e._v(",对应每一个 "),t("code",[e._v("AggregateResult")]),e._v("是否已经计算完成,并记录需要剩余计算的聚合函数数目 "),t("code",[e._v("remainingToCalculate")]),e._v("。布尔值列表和这个计数值将会使得某些聚合函数(如 "),t("code",[e._v("FIRST_VALUE")]),e._v(")在获得结果后,不需要再继续进行整个循环过程。")]),e._v(" "),t("p",[e._v("接下来,按照5.2节所介绍的 "),t("code",[e._v("aggregateReader")]),e._v(" 使用方法,更新 "),t("code",[e._v("AggregateResult")]),e._v(":")]),e._v(" "),t("div",{staticClass:"language- line-numbers-mode"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("while (aggregateReader.hasNextChunk()) {\n if (aggregateReader.canUseCurrentChunkStatistics()) {\n Statistics chunkStatistics = aggregateReader.currentChunkStatistics();\n \n // do some aggregate calculation using chunk statistics\n ...\n \n aggregateReader.skipCurrentChunk();\n continue;\n }\n\t \n while (aggregateReader.hasNextPage()) {\n\t if (aggregateReader.canUseCurrentPageStatistics()) {\n\t Statistics pageStatistic = aggregateReader.currentPageStatistics();\n\t \n\t // do some aggregate calculation using page statistics\n ...\n\t \n\t aggregateReader.skipCurrentPage();\n\t continue;\n\t } else {\n\t \tBatchData batchData = aggregateReader.nextPage();\n\t \t// do some aggregate calculation using batch data\n ...\n\t }\t \n }\n}\n")])]),e._v(" "),t("div",{staticClass:"line-numbers-wrapper"},[t("span",{staticClass:"line-number"},[e._v("1")]),t("br"),t("span",{staticClass:"line-number"},[e._v("2")]),t("br"),t("span",{staticClass:"line-number"},[e._v("3")]),t("br"),t("span",{staticClass:"line-number"},[e._v("4")]),t("br"),t("span",{staticClass:"line-number"},[e._v("5")]),t("br"),t("span",{staticClass:"line-number"},[e._v("6")]),t("br"),t("span",{staticClass:"line-number"},[e._v("7")]),t("br"),t("span",{staticClass:"line-number"},[e._v("8")]),t("br"),t("span",{staticClass:"line-number"},[e._v("9")]),t("br"),t("span",{staticClass:"line-number"},[e._v("10")]),t("br"),t("span",{staticClass:"line-number"},[e._v("11")]),t("br"),t("span",{staticClass:"line-number"},[e._v("12")]),t("br"),t("span",{staticClass:"line-number"},[e._v("13")]),t("br"),t("span",{staticClass:"line-number"},[e._v("14")]),t("br"),t("span",{staticClass:"line-number"},[e._v("15")]),t("br"),t("span",{staticClass:"line-number"},[e._v("16")]),t("br"),t("span",{staticClass:"line-number"},[e._v("17")]),t("br"),t("span",{staticClass:"line-number"},[e._v("18")]),t("br"),t("span",{staticClass:"line-number"},[e._v("19")]),t("br"),t("span",{staticClass:"line-number"},[e._v("20")]),t("br"),t("span",{staticClass:"line-number"},[e._v("21")]),t("br"),t("span",{staticClass:"line-number"},[e._v("22")]),t("br"),t("span",{staticClass:"line-number"},[e._v("23")]),t("br"),t("span",{staticClass:"line-number"},[e._v("24")]),t("br"),t("span",{staticClass:"line-number"},[e._v("25")]),t("br"),t("span",{staticClass:"line-number"},[e._v("26")]),t("br"),t("span",{staticClass:"line-number"},[e._v("27")]),t("br")])]),t("p",[e._v("需要注意的是,在对于每一个result进行更新之前,需要首先判断其是否已经被计算完(利用 "),t("code",[e._v("isCalculatedList")]),e._v(" 列表);每一次更新后,调用 "),t("code",[e._v("isCalculatedAggregationResult()")]),e._v(" 方法同时更新列表中的布尔值。如果列表中所有值均为true,即 "),t("code",[e._v("remainingToCalculate")]),e._v(" 值为0,证明所有聚合函数结果均已计算完,可以返回。")]),e._v(" "),t("div",{staticClass:"language- line-numbers-mode"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("if (Boolean.FALSE.equals(isCalculatedList.get(i))) {\n AggregateResult aggregateResult = aggregateResultList.get(i);\n ... // 更新\n if (aggregateResult.isCalculatedAggregationResult()) {\n isCalculatedList.set(i, true);\n remainingToCalculate--;\n if (remainingToCalculate == 0) {\n return aggregateResultList;\n }\n }\n}\n")])]),e._v(" "),t("div",{staticClass:"line-numbers-wrapper"},[t("span",{staticClass:"line-number"},[e._v("1")]),t("br"),t("span",{staticClass:"line-number"},[e._v("2")]),t("br"),t("span",{staticClass:"line-number"},[e._v("3")]),t("br"),t("span",{staticClass:"line-number"},[e._v("4")]),t("br"),t("span",{staticClass:"line-number"},[e._v("5")]),t("br"),t("span",{staticClass:"line-number"},[e._v("6")]),t("br"),t("span",{staticClass:"line-number"},[e._v("7")]),t("br"),t("span",{staticClass:"line-number"},[e._v("8")]),t("br"),t("span",{staticClass:"line-number"},[e._v("9")]),t("br"),t("span",{staticClass:"line-number"},[e._v("10")]),t("br"),t("span",{staticClass:"line-number"},[e._v("11")]),t("br")])]),t("p",[e._v("在使用 "),t("code",[e._v("overlapedPageData")]),e._v(" 进行更新时,由于获得每一个聚合函数结果都会遍历这个 batchData,因此需要调用 "),t("code",[e._v("resetBatchData()")]),e._v(" 方法将指针指向其开始位置,使得下一个函数可以遍历。")]),e._v(" "),t("h2",{attrs:{id:"带值过滤条件的聚合查询"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#带值过滤条件的聚合查询"}},[e._v("#")]),e._v(" 带值过滤条件的聚合查询")]),e._v(" "),t("p",[e._v("对于带值过滤条件的聚合查询,通过 "),t("code",[e._v("executeWithoutValueFilter()")]),e._v(" 方法获得结果并构建 dataSet。首先根据表达式创建 "),t("code",[e._v("timestampGenerator")]),e._v(",然后为每一个时间序列创建一个 "),t("code",[e._v("SeriesReaderByTimestamp")]),e._v(",放到 "),t("code",[e._v("readersOfSelectedSeries")]),e._v("列表中;为每一个查询创建一个创建一个聚合结果 "),t("code",[e._v("AggregateResult")]),e._v(",放到 "),t("code",[e._v("aggregateResults")]),e._v("列表中。")]),e._v(" "),t("p",[e._v("初始化完成后,调用 "),t("code",[e._v("aggregateWithValueFilter()")]),e._v(" 方法更新结果:")]),e._v(" "),t("div",{staticClass:"language- line-numbers-mode"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("while (timestampGenerator.hasNext()) {\n // 生成timestamps\n long[] timeArray = new long[aggregateFetchSize];\n int timeArrayLength = 0;\n for (int cnt = 0; cnt < aggregateFetchSize; cnt++) {\n if (!timestampGenerator.hasNext()) {\n break;\n }\n timeArray[timeArrayLength++] = timestampGenerator.next();\n }\n\n // 利用timestamps计算聚合结果\n for (int i = 0; i < readersOfSelectedSeries.size(); i++) {\n aggregateResults.get(i).updateResultUsingTimestamps(timeArray, timeArrayLength,\n readersOfSelectedSeries.get(i));\n }\n }\n")])]),e._v(" "),t("div",{staticClass:"line-numbers-wrapper"},[t("span",{staticClass:"line-number"},[e._v("1")]),t("br"),t("span",{staticClass:"line-number"},[e._v("2")]),t("br"),t("span",{staticClass:"line-number"},[e._v("3")]),t("br"),t("span",{staticClass:"line-number"},[e._v("4")]),t("br"),t("span",{staticClass:"line-number"},[e._v("5")]),t("br"),t("span",{staticClass:"line-number"},[e._v("6")]),t("br"),t("span",{staticClass:"line-number"},[e._v("7")]),t("br"),t("span",{staticClass:"line-number"},[e._v("8")]),t("br"),t("span",{staticClass:"line-number"},[e._v("9")]),t("br"),t("span",{staticClass:"line-number"},[e._v("10")]),t("br"),t("span",{staticClass:"line-number"},[e._v("11")]),t("br"),t("span",{staticClass:"line-number"},[e._v("12")]),t("br"),t("span",{staticClass:"line-number"},[e._v("13")]),t("br"),t("span",{staticClass:"line-number"},[e._v("14")]),t("br"),t("span",{staticClass:"line-number"},[e._v("15")]),t("br"),t("span",{staticClass:"line-number"},[e._v("16")]),t("br"),t("span",{staticClass:"line-number"},[e._v("17")]),t("br")])]),t("h2",{attrs:{id:"使用level来统计点数"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#使用level来统计点数"}},[e._v("#")]),e._v(" 使用Level来统计点数")]),e._v(" "),t("p",[e._v("对于count聚合查询,我们也可以使用level关键字来进一步汇总点数。")]),e._v(" "),t("p",[e._v("这个逻辑在 "),t("code",[e._v("AggregationExecutor")]),e._v("类里。")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("首先,把所有涉及到的时序按level来进行汇集,最后的路径。")]),e._v(" "),t("blockquote",[t("p",[e._v("例如把root.sg1.d1.s0,root.sg1.d2.s1按level=1汇集成root.sg1。")])])]),e._v(" "),t("li",[t("p",[e._v("然后调用上述的聚合逻辑求出所有时序的总点数信息,这个会返回RowRecord数据结构。")])]),e._v(" "),t("li",[t("p",[e._v("最后,把聚合查询返回的RowRecord按上述的final paths,进行累加,组合成新的RowRecord。")]),e._v(" "),t("blockquote",[t("p",[e._v("例如,把《root.sg1.d1.s0,3》,《root.sg1.d2.s1,4》聚合成《root.sg1,7》")])])])]),e._v(" "),t("blockquote",[t("p",[e._v("注意:")]),e._v(" "),t("ol",[t("li",[e._v("这里只支持count操作")]),e._v(" "),t("li",[e._v("root的层级level=0")])])])])}),[],!1,null,null,null);a.default=n.exports}}]);