blob: 7ce83e24d3d77376ae58c17fa6d9fda8fb2d942f [file] [log] [blame]
(window.webpackJsonp=window.webpackJsonp||[]).push([[295],{859:function(a,e,s){"use strict";s.r(e);var t=s(69),n=Object(t.a)({},(function(){var a=this,e=a.$createElement,s=a._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[s("h1",{attrs:{id:"最近时间戳-last-查询"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#最近时间戳-last-查询"}},[a._v("#")]),a._v(" 最近时间戳 Last 查询")]),a._v(" "),s("p",[a._v("Last 查询的主要逻辑在 LastQueryExecutor")]),a._v(" "),s("ul",[s("li",[a._v("org.apache.iotdb.db.query.executor.LastQueryExecutor")])]),a._v(" "),s("p",[a._v("Last查询对每个指定的时间序列执行"),s("code",[a._v("calculateLastPairForOneSeries")]),a._v("方法。")]),a._v(" "),s("h2",{attrs:{id:"读取mnode缓存数据"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#读取mnode缓存数据"}},[a._v("#")]),a._v(" 读取MNode缓存数据")]),a._v(" "),s("p",[a._v("我们在需要查询的时间序列所对应的MNode结构中添加Last数据缓存。"),s("code",[a._v("calculateLastPairForOneSeries")]),a._v("方法对于某个时间序列的Last查询,首先尝试读取MNode中的缓存数据。")]),a._v(" "),s("div",{staticClass:"language- line-numbers-mode"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("try {\n node = IoTDB.metaManager.getDeviceNodeWithAutoCreateStorageGroup(seriesPath.toString());\n} catch (MetadataException e) {\n throw new QueryProcessException(e);\n}\nif (((LeafMNode) node).getCachedLast() != null) {\n return ((LeafMNode) node).getCachedLast();\n}\n")])]),a._v(" "),s("div",{staticClass:"line-numbers-wrapper"},[s("span",{staticClass:"line-number"},[a._v("1")]),s("br"),s("span",{staticClass:"line-number"},[a._v("2")]),s("br"),s("span",{staticClass:"line-number"},[a._v("3")]),s("br"),s("span",{staticClass:"line-number"},[a._v("4")]),s("br"),s("span",{staticClass:"line-number"},[a._v("5")]),s("br"),s("span",{staticClass:"line-number"},[a._v("6")]),s("br"),s("span",{staticClass:"line-number"},[a._v("7")]),s("br"),s("span",{staticClass:"line-number"},[a._v("8")]),s("br")])]),s("p",[a._v("如果发现缓存没有被写入过,则执行下面的标准查询流程读取TsFile数据。")]),a._v(" "),s("h2",{attrs:{id:"last标准查询流程"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#last标准查询流程"}},[a._v("#")]),a._v(" Last标准查询流程")]),a._v(" "),s("p",[a._v("Last标准查询流程需要以倒序方式扫描顺序文件和乱序文件,一旦得到满足要求的Last查询结果就将其写回到MNode缓存中并返回。算法中对顺序文件和乱序文件分别进行处理。")]),a._v(" "),s("ul",[s("li",[s("p",[a._v("顺序文件由于是按照写入时间已经排好序,因此直接使用"),s("code",[a._v("loadTimeSeriesMetadata()")]),a._v("方法取出最后一个不为空的"),s("code",[a._v("TimeseriesMetadata")]),a._v("。若"),s("code",[a._v("TimeseriesMetadata")]),a._v("的统计数据可用即可直接得到Last时间戳和对应的值;如不可用则需要使用"),s("code",[a._v("loadChunkMetadataList()")]),a._v("方法得到下一层的最后一个"),s("code",[a._v("ChunkMetadata")]),a._v(",通过统计数据得到Last结果。")]),a._v(" "),s("div",{staticClass:"language- line-numbers-mode"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("for (int i = seqFileResources.size() - 1; i >= 0; i--) {\n TimeseriesMetadata timeseriesMetadata = FileLoaderUtils.loadTimeSeriesMetadata(\n seqFileResources.get(i), seriesPath, context, null, sensors);\n if (timeseriesMetadata != null) {\n if (!timeseriesMetadata.isModified()) {\n Statistics timeseriesMetadataStats = timeseriesMetadata.getStatistics();\n resultPair = constructLastPair(\n timeseriesMetadataStats.getEndTime(),\n timeseriesMetadataStats.getLastValue(),\n tsDataType);\n break;\n } else {\n List<ChunkMetadata> chunkMetadataList = timeseriesMetadata.loadChunkMetadataList();\n if (!chunkMetadataList.isEmpty()) {\n ChunkMetadata lastChunkMetaData = chunkMetadataList.get(chunkMetadataList.size() - 1);\n Statistics chunkStatistics = lastChunkMetaData.getStatistics();\n resultPair =\n constructLastPair(\n chunkStatistics.getEndTime(), chunkStatistics.getLastValue(), tsDataType);\n break;\n }\n }\n }\n }\n")])]),a._v(" "),s("div",{staticClass:"line-numbers-wrapper"},[s("span",{staticClass:"line-number"},[a._v("1")]),s("br"),s("span",{staticClass:"line-number"},[a._v("2")]),s("br"),s("span",{staticClass:"line-number"},[a._v("3")]),s("br"),s("span",{staticClass:"line-number"},[a._v("4")]),s("br"),s("span",{staticClass:"line-number"},[a._v("5")]),s("br"),s("span",{staticClass:"line-number"},[a._v("6")]),s("br"),s("span",{staticClass:"line-number"},[a._v("7")]),s("br"),s("span",{staticClass:"line-number"},[a._v("8")]),s("br"),s("span",{staticClass:"line-number"},[a._v("9")]),s("br"),s("span",{staticClass:"line-number"},[a._v("10")]),s("br"),s("span",{staticClass:"line-number"},[a._v("11")]),s("br"),s("span",{staticClass:"line-number"},[a._v("12")]),s("br"),s("span",{staticClass:"line-number"},[a._v("13")]),s("br"),s("span",{staticClass:"line-number"},[a._v("14")]),s("br"),s("span",{staticClass:"line-number"},[a._v("15")]),s("br"),s("span",{staticClass:"line-number"},[a._v("16")]),s("br"),s("span",{staticClass:"line-number"},[a._v("17")]),s("br"),s("span",{staticClass:"line-number"},[a._v("18")]),s("br"),s("span",{staticClass:"line-number"},[a._v("19")]),s("br"),s("span",{staticClass:"line-number"},[a._v("20")]),s("br"),s("span",{staticClass:"line-number"},[a._v("21")]),s("br"),s("span",{staticClass:"line-number"},[a._v("22")]),s("br"),s("span",{staticClass:"line-number"},[a._v("23")]),s("br"),s("span",{staticClass:"line-number"},[a._v("24")]),s("br")])])]),a._v(" "),s("li",[s("p",[a._v("对于乱序文件,需要遍历所有不为空的"),s("code",[a._v("TimeseriesMetadata")]),a._v("结构并更新当前最大时间戳的Last数据,直到扫描完所有乱序文件为止。需要注意的是当多个"),s("code",[a._v("ChunkMetadata")]),a._v("拥有相同的最大时间戳时,我们取"),s("code",[a._v("version")]),a._v("值最大的"),s("code",[a._v("ChunkMatadata")]),a._v("中的数据作为Last的结果。")]),a._v(" "),s("div",{staticClass:"language- line-numbers-mode"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("long version = 0;\nfor (TsFileResource resource : unseqFileResources) {\n if (resource.getEndTime(seriesPath.getDevice()) < resultPair.getTimestamp()) {\n continue;\n }\n TimeseriesMetadata timeseriesMetadata =\n FileLoaderUtils.loadTimeSeriesMetadata(resource, seriesPath, context, null, sensors);\n if (timeseriesMetadata != null) {\n for (ChunkMetadata chunkMetaData : timeseriesMetadata.loadChunkMetadataList()) {\n if (chunkMetaData.getEndTime() == resultPair.getTimestamp()\n && chunkMetaData.getVersion() > version) {\n Statistics chunkStatistics = chunkMetaData.getStatistics();\n resultPair =\n constructLastPair(\n chunkStatistics.getEndTime(), chunkStatistics.getLastValue(), tsDataType);\n version = chunkMetaData.getVersion();\n }\n }\n }\n}\n")])]),a._v(" "),s("div",{staticClass:"line-numbers-wrapper"},[s("span",{staticClass:"line-number"},[a._v("1")]),s("br"),s("span",{staticClass:"line-number"},[a._v("2")]),s("br"),s("span",{staticClass:"line-number"},[a._v("3")]),s("br"),s("span",{staticClass:"line-number"},[a._v("4")]),s("br"),s("span",{staticClass:"line-number"},[a._v("5")]),s("br"),s("span",{staticClass:"line-number"},[a._v("6")]),s("br"),s("span",{staticClass:"line-number"},[a._v("7")]),s("br"),s("span",{staticClass:"line-number"},[a._v("8")]),s("br"),s("span",{staticClass:"line-number"},[a._v("9")]),s("br"),s("span",{staticClass:"line-number"},[a._v("10")]),s("br"),s("span",{staticClass:"line-number"},[a._v("11")]),s("br"),s("span",{staticClass:"line-number"},[a._v("12")]),s("br"),s("span",{staticClass:"line-number"},[a._v("13")]),s("br"),s("span",{staticClass:"line-number"},[a._v("14")]),s("br"),s("span",{staticClass:"line-number"},[a._v("15")]),s("br"),s("span",{staticClass:"line-number"},[a._v("16")]),s("br"),s("span",{staticClass:"line-number"},[a._v("17")]),s("br"),s("span",{staticClass:"line-number"},[a._v("18")]),s("br"),s("span",{staticClass:"line-number"},[a._v("19")]),s("br"),s("span",{staticClass:"line-number"},[a._v("20")]),s("br")])])]),a._v(" "),s("li",[s("p",[a._v("最后将查询结果写入到MNode的Last缓存")]),a._v(" "),s("div",{staticClass:"language- line-numbers-mode"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("((LeafMNode) node).updateCachedLast(resultPair, false, Long.MIN_VALUE);\n")])]),a._v(" "),s("div",{staticClass:"line-numbers-wrapper"},[s("span",{staticClass:"line-number"},[a._v("1")]),s("br")])])])]),a._v(" "),s("h2",{attrs:{id:"last-缓存更新策略"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#last-缓存更新策略"}},[a._v("#")]),a._v(" Last 缓存更新策略")]),a._v(" "),s("p",[a._v("Last缓存更新的逻辑位于"),s("code",[a._v("LeafMNode")]),a._v("的"),s("code",[a._v("updateCachedLast")]),a._v("方法内,这里引入两个额外的参数"),s("code",[a._v("highPriorityUpdate")]),a._v("和"),s("code",[a._v("latestFlushTime")]),a._v("。"),s("code",[a._v("highPriorityUpdate")]),a._v("用来表示本次更新是否是高优先级的,新数据写入而导致的缓存更新都被认为是高优先级更新,而查询时更新缓存默认为低优先级更新。"),s("code",[a._v("latestFlushTime")]),a._v("用来记录当前已被写回到磁盘的数据的最大时间戳。")]),a._v(" "),s("p",[a._v("缓存更新的策略如下:")]),a._v(" "),s("ol",[s("li",[a._v("当缓存中没有记录时,对于查询到的Last数据,将查询的结果直接写入到缓存中。")]),a._v(" "),s("li",[a._v("当缓存中没有记录时,对于写入的最新数据如果时间戳大于或等于"),s("code",[a._v("latestFlushTime")]),a._v(",则将写入的数据写入到缓存中。")]),a._v(" "),s("li",[a._v("当缓存中已有记录时,根据查询或写入的数据时间戳与当前缓存中时间戳作对比。写入的数据具有高优先级,时间戳不小于缓存记录则更新缓存;查询出的数据低优先级,必须大于缓存记录的时间戳才更新缓存。")])]),a._v(" "),s("p",[a._v("具体代码如下")]),a._v(" "),s("div",{staticClass:"language- line-numbers-mode"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("public synchronized void updateCachedLast(\n TimeValuePair timeValuePair, boolean highPriorityUpdate, Long latestFlushedTime) {\n if (timeValuePair == null || timeValuePair.getValue() == null) return;\n \n if (cachedLastValuePair == null) {\n // If no cached last, (1) a last query (2) an unseq insertion or (3) a seq insertion will update cache.\n if (!highPriorityUpdate || latestFlushedTime <= timeValuePair.getTimestamp()) {\n cachedLastValuePair =\n new TimeValuePair(timeValuePair.getTimestamp(), timeValuePair.getValue());\n }\n } else if (timeValuePair.getTimestamp() > cachedLastValuePair.getTimestamp()\n || (timeValuePair.getTimestamp() == cachedLastValuePair.getTimestamp()\n && highPriorityUpdate)) {\n cachedLastValuePair.setTimestamp(timeValuePair.getTimestamp());\n cachedLastValuePair.setValue(timeValuePair.getValue());\n }\n}\n")])]),a._v(" "),s("div",{staticClass:"line-numbers-wrapper"},[s("span",{staticClass:"line-number"},[a._v("1")]),s("br"),s("span",{staticClass:"line-number"},[a._v("2")]),s("br"),s("span",{staticClass:"line-number"},[a._v("3")]),s("br"),s("span",{staticClass:"line-number"},[a._v("4")]),s("br"),s("span",{staticClass:"line-number"},[a._v("5")]),s("br"),s("span",{staticClass:"line-number"},[a._v("6")]),s("br"),s("span",{staticClass:"line-number"},[a._v("7")]),s("br"),s("span",{staticClass:"line-number"},[a._v("8")]),s("br"),s("span",{staticClass:"line-number"},[a._v("9")]),s("br"),s("span",{staticClass:"line-number"},[a._v("10")]),s("br"),s("span",{staticClass:"line-number"},[a._v("11")]),s("br"),s("span",{staticClass:"line-number"},[a._v("12")]),s("br"),s("span",{staticClass:"line-number"},[a._v("13")]),s("br"),s("span",{staticClass:"line-number"},[a._v("14")]),s("br"),s("span",{staticClass:"line-number"},[a._v("15")]),s("br"),s("span",{staticClass:"line-number"},[a._v("16")]),s("br"),s("span",{staticClass:"line-number"},[a._v("17")]),s("br")])])])}),[],!1,null,null,null);e.default=n.exports}}]);