blob: 7d8196a9b7228e262645d6353aaa8c215e476c59 [file] [log] [blame]
(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{599:function(e,t,a){"use strict";a.r(t);var s=a(70),n=Object(s.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"aggregation-query"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#aggregation-query"}},[e._v("#")]),e._v(" Aggregation query")]),e._v(" "),a("p",[e._v("The main logic of the aggregation query is in AggregateExecutor")]),e._v(" "),a("ul",[a("li",[e._v("org.apache.iotdb.db.query.executor.AggregationExecutor")])]),e._v(" "),a("h2",{attrs:{id:"aggregation-query-without-value-filter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#aggregation-query-without-value-filter"}},[e._v("#")]),e._v(" Aggregation query without value filter")]),e._v(" "),a("p",[e._v("For aggregate queries without value filters, the results are obtained by the "),a("code",[e._v("executeWithoutValueFilter()")]),e._v(" method and a dataSet is constructed. First use the "),a("code",[e._v("mergeSameSeries()")]),e._v(" method to merge aggregate queries for the same time series. For example: if you need to calculate count(s1), sum(s2), count(s3), sum(s1), you need to calculate two aggregation values of s1, then the pathToAggrIndexesMap result will be: s1-> 0, 3; s2-> 1; s3-> 2.")]),e._v(" "),a("p",[e._v("Then you will get "),a("code",[e._v("pathToAggrIndexesMap")]),e._v(", where each entry is an aggregate query of series, so you can calculate its aggregate value "),a("code",[e._v("aggregateResults")]),e._v(" by calling the "),a("code",[e._v("groupAggregationsBySeries()")]),e._v(" method. Before you finally create the result set, you need to restore its order to the order of the user query. Finally use the "),a("code",[e._v("constructDataSet()")]),e._v(" method to create a result set and return it.")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("groupAggregationsBySeries ()")]),e._v(" method is explained in detail below. First create an "),a("code",[e._v("IAggregateReader")]),e._v(":")]),e._v(" "),a("div",{staticClass:"language- line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("IAggregateReader seriesReader = new SeriesAggregateReader(\n pathToAggrIndexes.getKey(), tsDataType, context, QueryResourceManager.getInstance()\n .getQueryDataSource(seriesPath, context, timeFilter), timeFilter, null);\n")])]),e._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[e._v("1")]),a("br"),a("span",{staticClass:"line-number"},[e._v("2")]),a("br"),a("span",{staticClass:"line-number"},[e._v("3")]),a("br")])]),a("p",[e._v("For each entry (that is, series), first create an aggregate result "),a("code",[e._v("AggregateResult")]),e._v(" for each aggregate query. Maintain a boolean list "),a("code",[e._v("isCalculatedList")]),e._v(", corresponding to whether each "),a("code",[e._v("AggregateResult")]),e._v(" has been calculated. Record the remaining number of functions to be calculated in "),a("code",[e._v("remainingToCalculate")]),e._v(". The list of boolean values and this count value will make some aggregate functions (such as "),a("code",[e._v("FIRST_VALUE")]),e._v(") not need to continue the entire loop process after obtaining the result.")]),e._v(" "),a("p",[e._v("Next, update "),a("code",[e._v("AggregateResult")]),e._v(" according to the usage method of "),a("code",[e._v("aggregateReader")]),e._v(" introduced in Section 5.2:")]),e._v(" "),a("div",{staticClass:"language- line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("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(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[e._v("1")]),a("br"),a("span",{staticClass:"line-number"},[e._v("2")]),a("br"),a("span",{staticClass:"line-number"},[e._v("3")]),a("br"),a("span",{staticClass:"line-number"},[e._v("4")]),a("br"),a("span",{staticClass:"line-number"},[e._v("5")]),a("br"),a("span",{staticClass:"line-number"},[e._v("6")]),a("br"),a("span",{staticClass:"line-number"},[e._v("7")]),a("br"),a("span",{staticClass:"line-number"},[e._v("8")]),a("br"),a("span",{staticClass:"line-number"},[e._v("9")]),a("br"),a("span",{staticClass:"line-number"},[e._v("10")]),a("br"),a("span",{staticClass:"line-number"},[e._v("11")]),a("br"),a("span",{staticClass:"line-number"},[e._v("12")]),a("br"),a("span",{staticClass:"line-number"},[e._v("13")]),a("br"),a("span",{staticClass:"line-number"},[e._v("14")]),a("br"),a("span",{staticClass:"line-number"},[e._v("15")]),a("br"),a("span",{staticClass:"line-number"},[e._v("16")]),a("br"),a("span",{staticClass:"line-number"},[e._v("17")]),a("br"),a("span",{staticClass:"line-number"},[e._v("18")]),a("br"),a("span",{staticClass:"line-number"},[e._v("19")]),a("br"),a("span",{staticClass:"line-number"},[e._v("20")]),a("br"),a("span",{staticClass:"line-number"},[e._v("21")]),a("br"),a("span",{staticClass:"line-number"},[e._v("22")]),a("br"),a("span",{staticClass:"line-number"},[e._v("23")]),a("br"),a("span",{staticClass:"line-number"},[e._v("24")]),a("br"),a("span",{staticClass:"line-number"},[e._v("25")]),a("br"),a("span",{staticClass:"line-number"},[e._v("26")]),a("br"),a("span",{staticClass:"line-number"},[e._v("27")]),a("br")])]),a("p",[e._v("It should be noted that before updating each result, you need to first determine whether it has been calculated (using the isCalculatedList list); after each update, call the isCalculatedAggregationResult () method to update the boolean values in the list . If all values in the list are true, that is, the value of "),a("code",[e._v("remainingToCalculate")]),e._v(" is 0, it proves that all aggregate function results have been calculated and can be returned.")]),e._v(" "),a("div",{staticClass:"language- line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("if (Boolean.FALSE.equals(isCalculatedList.get(i))) {\n AggregateResult aggregateResult = aggregateResultList.get(i);\n ... // update\n if (aggregateResult.isCalculatedAggregationResult()) {\n isCalculatedList.set(i, true);\n remainingToCalculate--;\n if (remainingToCalculate == 0) {\n return aggregateResultList;\n }\n }\n}\n")])]),e._v(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[e._v("1")]),a("br"),a("span",{staticClass:"line-number"},[e._v("2")]),a("br"),a("span",{staticClass:"line-number"},[e._v("3")]),a("br"),a("span",{staticClass:"line-number"},[e._v("4")]),a("br"),a("span",{staticClass:"line-number"},[e._v("5")]),a("br"),a("span",{staticClass:"line-number"},[e._v("6")]),a("br"),a("span",{staticClass:"line-number"},[e._v("7")]),a("br"),a("span",{staticClass:"line-number"},[e._v("8")]),a("br"),a("span",{staticClass:"line-number"},[e._v("9")]),a("br"),a("span",{staticClass:"line-number"},[e._v("10")]),a("br"),a("span",{staticClass:"line-number"},[e._v("11")]),a("br")])]),a("p",[e._v("When using "),a("code",[e._v("overlapedPageData")]),e._v(" to update, since each batch function result will traverse this batchData, you need to call the"),a("code",[e._v("resetBatchData ()")]),e._v("method to point the pointer to its starting position, so that the next function can traverse.")]),e._v(" "),a("h2",{attrs:{id:"aggregated-query-with-value-filter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#aggregated-query-with-value-filter"}},[e._v("#")]),e._v(" Aggregated query with value filter")]),e._v(" "),a("p",[e._v("For an aggregate query with a value filter, obtain the results through the "),a("code",[e._v("executeWithoutValueFilter()")]),e._v(" method and build a dataSet. First create a "),a("code",[e._v("timestampGenerator")]),e._v(" based on the expression, then create a "),a("code",[e._v("SeriesReaderByTimestamp")]),e._v(" for each time series and place it in the "),a("code",[e._v("readersOfSelectedSeries")]),e._v(" list; create an aggregate result for each query as "),a("code",[e._v("AggregateResult")]),e._v(", and place it in the "),a("code",[e._v("aggregateResults")]),e._v(" list.")]),e._v(" "),a("p",[e._v("After initialization is complete, call the "),a("code",[e._v("aggregateWithValueFilter()")]),e._v(" method to update the result:")]),e._v(" "),a("div",{staticClass:"language- line-numbers-mode"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("while (timestampGenerator.hasNext()) {\n // Generate 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 // Calculate aggregate results using 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(" "),a("div",{staticClass:"line-numbers-wrapper"},[a("span",{staticClass:"line-number"},[e._v("1")]),a("br"),a("span",{staticClass:"line-number"},[e._v("2")]),a("br"),a("span",{staticClass:"line-number"},[e._v("3")]),a("br"),a("span",{staticClass:"line-number"},[e._v("4")]),a("br"),a("span",{staticClass:"line-number"},[e._v("5")]),a("br"),a("span",{staticClass:"line-number"},[e._v("6")]),a("br"),a("span",{staticClass:"line-number"},[e._v("7")]),a("br"),a("span",{staticClass:"line-number"},[e._v("8")]),a("br"),a("span",{staticClass:"line-number"},[e._v("9")]),a("br"),a("span",{staticClass:"line-number"},[e._v("10")]),a("br"),a("span",{staticClass:"line-number"},[e._v("11")]),a("br"),a("span",{staticClass:"line-number"},[e._v("12")]),a("br"),a("span",{staticClass:"line-number"},[e._v("13")]),a("br"),a("span",{staticClass:"line-number"},[e._v("14")]),a("br"),a("span",{staticClass:"line-number"},[e._v("15")]),a("br"),a("span",{staticClass:"line-number"},[e._v("16")]),a("br"),a("span",{staticClass:"line-number"},[e._v("17")]),a("br")])]),a("h2",{attrs:{id:"aggregated-query-with-level"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#aggregated-query-with-level"}},[e._v("#")]),e._v(" Aggregated query with level")]),e._v(" "),a("p",[e._v("After aggregated query, we could also to count the total number of points of")]),e._v(" "),a("p",[e._v("each node at the given level in current Metadata Tree.")]),e._v(" "),a("p",[e._v("The logic is in the "),a("code",[e._v("AggregationExecutor")]),e._v(" class.")]),e._v(" "),a("ol",[a("li",[a("p",[e._v("In the beginning, get the final paths group by level and the origin path index to final path.")]),e._v(" "),a("blockquote",[a("p",[e._v("For example, we could get final path "),a("code",[e._v("root.sg1")]),e._v(" by "),a("code",[e._v("root.sg1.d1.s0,root.sg1.d2.s1")]),e._v(" and "),a("code",[e._v("level=1")]),e._v(".")])])]),e._v(" "),a("li",[a("p",[e._v("Then, get the aggregated query result: RowRecord.")])]),e._v(" "),a("li",[a("p",[e._v("Finally, merge each RowRecord to NewRecord, which has fields like <final path, count>.")]),e._v(" "),a("blockquote",[a("p",[e._v("For example, we will get new RowRecord "),a("code",[e._v("<root.sg1,7>")]),e._v(" by "),a("code",[e._v("<root.sg1.d1.s0, 3>, <root.sg1.d2.s1, 4>")]),e._v(" and level=1.")])])])]),e._v(" "),a("blockquote",[a("p",[e._v("Attention:")]),e._v(" "),a("ol",[a("li",[e._v("only support count aggregation")]),e._v(" "),a("li",[e._v("root's level == 0")])])])])}),[],!1,null,null,null);t.default=n.exports}}]);