| /* |
| * 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.carbondata.core.scan.scanner.impl; |
| |
| import java.io.IOException; |
| import java.util.BitSet; |
| |
| import org.apache.carbondata.core.constants.CarbonCommonConstants; |
| import org.apache.carbondata.core.datastore.DataRefNode; |
| import org.apache.carbondata.core.datastore.FileReader; |
| import org.apache.carbondata.core.datastore.chunk.DimensionColumnPage; |
| import org.apache.carbondata.core.datastore.chunk.impl.DimensionRawColumnChunk; |
| import org.apache.carbondata.core.datastore.chunk.impl.MeasureRawColumnChunk; |
| import org.apache.carbondata.core.datastore.page.ColumnPage; |
| import org.apache.carbondata.core.scan.executor.infos.BlockExecutionInfo; |
| import org.apache.carbondata.core.scan.expression.exception.FilterUnsupportedException; |
| import org.apache.carbondata.core.scan.filter.executer.FilterExecutor; |
| import org.apache.carbondata.core.scan.filter.executer.ImplicitColumnFilterExecutor; |
| import org.apache.carbondata.core.scan.processor.RawBlockletColumnChunks; |
| import org.apache.carbondata.core.scan.result.BlockletScannedResult; |
| import org.apache.carbondata.core.scan.result.impl.FilterQueryScannedResult; |
| import org.apache.carbondata.core.scan.scanner.LazyBlockletLoader; |
| import org.apache.carbondata.core.stats.QueryStatistic; |
| import org.apache.carbondata.core.stats.QueryStatisticsConstants; |
| import org.apache.carbondata.core.stats.QueryStatisticsModel; |
| import org.apache.carbondata.core.util.BitSetGroup; |
| import org.apache.carbondata.core.util.CarbonProperties; |
| import org.apache.carbondata.core.util.CarbonUtil; |
| |
| /** |
| * Below class will be used for filter query processing |
| * this class will be first apply the filter then it will read the column page if |
| * required and return the scanned result |
| */ |
| public class BlockletFilterScanner extends BlockletFullScanner { |
| |
| /** |
| * filter executor to evaluate filter condition |
| */ |
| private FilterExecutor filterExecutor; |
| /** |
| * this will be used to apply min max |
| * this will be useful for dimension column which is on the right side |
| * as node finder will always give tentative blocks, if column data stored individually |
| * and data is in sorted order then we can check whether filter is in the range of min max or not |
| * if it present then only we can apply filter on complete data. |
| * this will be very useful in case of sparse data when rows are |
| * repeating. |
| */ |
| private boolean isMinMaxEnabled; |
| |
| private QueryStatisticsModel queryStatisticsModel; |
| |
| private boolean useBitSetPipeLine; |
| |
| public BlockletFilterScanner(BlockExecutionInfo blockExecutionInfo, |
| QueryStatisticsModel queryStatisticsModel) { |
| super(blockExecutionInfo, queryStatisticsModel); |
| // to check whether min max is enabled or not |
| String minMaxEnableValue = CarbonProperties.getInstance() |
| .getProperty(CarbonCommonConstants.CARBON_QUERY_MIN_MAX_ENABLED, |
| CarbonCommonConstants.MIN_MAX_DEFAULT_VALUE); |
| if (null != minMaxEnableValue) { |
| isMinMaxEnabled = Boolean.parseBoolean(minMaxEnableValue); |
| } |
| // get the filter tree |
| this.filterExecutor = blockExecutionInfo.getFilterExecutorTree(); |
| this.queryStatisticsModel = queryStatisticsModel; |
| |
| String useBitSetPipeLine = CarbonProperties.getInstance() |
| .getProperty(CarbonCommonConstants.BITSET_PIPE_LINE, |
| CarbonCommonConstants.BITSET_PIPE_LINE_DEFAULT); |
| if (null != useBitSetPipeLine) { |
| this.useBitSetPipeLine = Boolean.parseBoolean(useBitSetPipeLine); |
| } |
| } |
| |
| /** |
| * Below method will be used to process the block |
| * |
| * @param rawBlockletColumnChunks block chunk holder which holds the data |
| * @throws FilterUnsupportedException |
| */ |
| @Override |
| public BlockletScannedResult scanBlocklet(RawBlockletColumnChunks rawBlockletColumnChunks) |
| throws IOException, FilterUnsupportedException { |
| if (blockExecutionInfo.isDirectVectorFill()) { |
| return executeFilterForPages(rawBlockletColumnChunks); |
| } else { |
| return executeFilter(rawBlockletColumnChunks); |
| } |
| } |
| |
| @Override |
| public boolean isScanRequired(DataRefNode dataBlock) { |
| // adding statistics for number of pages |
| QueryStatistic totalPagesScanned = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.TOTAL_PAGE_SCANNED); |
| totalPagesScanned.addCountStatistic(QueryStatisticsConstants.TOTAL_PAGE_SCANNED, |
| totalPagesScanned.getCount() + dataBlock.numberOfPages()); |
| QueryStatistic totalBlockletStatistic = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.TOTAL_BLOCKLET_NUM); |
| totalBlockletStatistic.addCountStatistic(QueryStatisticsConstants.TOTAL_BLOCKLET_NUM, |
| totalBlockletStatistic.getCount() + 1); |
| // apply min max |
| if (isMinMaxEnabled) { |
| if (null == dataBlock.getColumnsMaxValue() |
| || null == dataBlock.getColumnsMinValue()) { |
| return true; |
| } |
| BitSet bitSet = null; |
| // check for implicit include filter instance |
| if (filterExecutor instanceof ImplicitColumnFilterExecutor) { |
| String blockletId = blockExecutionInfo.getBlockIdString() + |
| CarbonCommonConstants.FILE_SEPARATOR + dataBlock.blockletIndex(); |
| bitSet = ((ImplicitColumnFilterExecutor) filterExecutor) |
| .isFilterValuesPresentInBlockOrBlocklet( |
| dataBlock.getColumnsMaxValue(), |
| dataBlock.getColumnsMinValue(), blockletId, dataBlock.minMaxFlagArray()); |
| } else { |
| bitSet = this.filterExecutor |
| .isScanRequired(dataBlock.getColumnsMaxValue(), |
| dataBlock.getColumnsMinValue(), dataBlock.minMaxFlagArray()); |
| } |
| return !bitSet.isEmpty(); |
| } |
| return true; |
| } |
| |
| @Override |
| public void readBlocklet(RawBlockletColumnChunks rawBlockletColumnChunks) throws IOException { |
| long startTime = System.currentTimeMillis(); |
| this.filterExecutor.readColumnChunks(rawBlockletColumnChunks); |
| // adding statistics for carbon read time |
| QueryStatistic readTime = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.READ_BLOCKlET_TIME); |
| readTime.addCountStatistic(QueryStatisticsConstants.READ_BLOCKlET_TIME, |
| readTime.getCount() + (System.currentTimeMillis() - startTime)); |
| } |
| |
| /** |
| * This method will process the data in below order |
| * 1. first apply min max on the filter tree and check whether any of the filter |
| * is fall on the range of min max, if not then return empty result |
| * 2. If filter falls on min max range then apply filter on actual |
| * data and get the filtered row index |
| * 3. if row index is empty then return the empty result |
| * 4. if row indexes is not empty then read only those blocks(measure or dimension) |
| * which was present in the query but not present in the filter, as while applying filter |
| * some of the blocks where already read and present in chunk holder so not need to |
| * read those blocks again, this is to avoid reading of same blocks which was already read |
| * 5. Set the blocks and filter indexes to result |
| * |
| * @param rawBlockletColumnChunks |
| * @throws FilterUnsupportedException |
| */ |
| private BlockletScannedResult executeFilter(RawBlockletColumnChunks rawBlockletColumnChunks) |
| throws FilterUnsupportedException, IOException { |
| long startTime = System.currentTimeMillis(); |
| // set the indexed data if it has any during fgIndex pruning. |
| BitSetGroup fgBitSetGroup = rawBlockletColumnChunks.getDataBlock().getIndexedData(); |
| rawBlockletColumnChunks.setBitSetGroup(fgBitSetGroup); |
| // apply filter on actual data, for each page |
| BitSetGroup bitSetGroup = this.filterExecutor.applyFilter(rawBlockletColumnChunks, |
| useBitSetPipeLine); |
| // if filter result is empty then return with empty result |
| if (bitSetGroup.isEmpty()) { |
| CarbonUtil.freeMemory(rawBlockletColumnChunks.getDimensionRawColumnChunks(), |
| rawBlockletColumnChunks.getMeasureRawColumnChunks()); |
| |
| QueryStatistic scanTime = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.SCAN_BLOCKlET_TIME); |
| scanTime.addCountStatistic(QueryStatisticsConstants.SCAN_BLOCKlET_TIME, |
| scanTime.getCount() + (System.currentTimeMillis() - startTime)); |
| |
| QueryStatistic scannedBlocklets = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.BLOCKLET_SCANNED_NUM); |
| scannedBlocklets.addCountStatistic(QueryStatisticsConstants.BLOCKLET_SCANNED_NUM, |
| scannedBlocklets.getCount() + 1); |
| |
| QueryStatistic scannedPages = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.PAGE_SCANNED); |
| scannedPages.addCountStatistic(QueryStatisticsConstants.PAGE_SCANNED, |
| scannedPages.getCount() + bitSetGroup.getScannedPages()); |
| return createEmptyResult(); |
| } |
| |
| BlockletScannedResult scannedResult = |
| new FilterQueryScannedResult(blockExecutionInfo, queryStatisticsModel); |
| scannedResult.setBlockletId(blockExecutionInfo.getBlockIdString(), |
| String.valueOf(rawBlockletColumnChunks.getDataBlock().blockletIndex())); |
| // valid scanned blocklet |
| QueryStatistic validScannedBlockletStatistic = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.VALID_SCAN_BLOCKLET_NUM); |
| validScannedBlockletStatistic |
| .addCountStatistic(QueryStatisticsConstants.VALID_SCAN_BLOCKLET_NUM, |
| validScannedBlockletStatistic.getCount() + 1); |
| // adding statistics for valid number of pages |
| QueryStatistic validPages = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.VALID_PAGE_SCANNED); |
| validPages.addCountStatistic(QueryStatisticsConstants.VALID_PAGE_SCANNED, |
| validPages.getCount() + bitSetGroup.getValidPages()); |
| |
| QueryStatistic scannedBlocklets = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.BLOCKLET_SCANNED_NUM); |
| scannedBlocklets.addCountStatistic(QueryStatisticsConstants.BLOCKLET_SCANNED_NUM, |
| scannedBlocklets.getCount() + 1); |
| |
| QueryStatistic scannedPages = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.PAGE_SCANNED); |
| scannedPages.addCountStatistic(QueryStatisticsConstants.PAGE_SCANNED, |
| scannedPages.getCount() + bitSetGroup.getScannedPages()); |
| int[] pageFilteredRowCount = new int[bitSetGroup.getNumberOfPages()]; |
| // get the row indexes from bit set for each page |
| int[][] pageFilteredRowId = new int[bitSetGroup.getNumberOfPages()][]; |
| int numPages = pageFilteredRowId.length; |
| for (int pageId = 0; pageId < numPages; pageId++) { |
| BitSet bitSet = bitSetGroup.getBitSet(pageId); |
| if (bitSet != null && !bitSet.isEmpty()) { |
| int[] matchedRowId = new int[bitSet.cardinality()]; |
| int index = 0; |
| for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) { |
| matchedRowId[index++] = i; |
| } |
| pageFilteredRowCount[pageId] = matchedRowId.length; |
| pageFilteredRowId[pageId] = matchedRowId; |
| } |
| } |
| |
| FileReader fileReader = rawBlockletColumnChunks.getFileReader(); |
| |
| DimensionRawColumnChunk[] dimensionRawColumnChunks = |
| new DimensionRawColumnChunk[blockExecutionInfo.getTotalNumberDimensionToRead()]; |
| int numDimensionChunks = dimensionRawColumnChunks.length; |
| // read dimension chunk blocks from file which is not present |
| for (int chunkIndex = 0; chunkIndex < numDimensionChunks; chunkIndex++) { |
| dimensionRawColumnChunks[chunkIndex] = |
| rawBlockletColumnChunks.getDimensionRawColumnChunks()[chunkIndex]; |
| } |
| //dimensionReadTime is the time required to read the data from dimension array |
| long totalReadTime = System.currentTimeMillis(); |
| int[][] allSelectedDimensionColumnIndexRange = |
| blockExecutionInfo.getAllSelectedDimensionColumnIndexRange(); |
| DimensionRawColumnChunk[] projectionListDimensionChunk = rawBlockletColumnChunks.getDataBlock() |
| .readDimensionChunks(fileReader, allSelectedDimensionColumnIndexRange); |
| totalReadTime = System.currentTimeMillis() - totalReadTime; |
| |
| for (int[] columnIndexRange : allSelectedDimensionColumnIndexRange) { |
| System.arraycopy(projectionListDimensionChunk, columnIndexRange[0], |
| dimensionRawColumnChunks, columnIndexRange[0], |
| columnIndexRange[1] + 1 - columnIndexRange[0]); |
| } |
| |
| /** |
| * Below code is to read the dimension which is not read as part of filter or projection |
| * for example in case of or filter if first filter matches all the rows then it will not read |
| * second filter column and if it is present as part of projection, so needs to be read |
| */ |
| long filterDimensionReadTime = System.currentTimeMillis(); |
| int[] projectionListDimensionIndexes = blockExecutionInfo.getProjectionListDimensionIndexes(); |
| for (int projectionListDimensionIndex : projectionListDimensionIndexes) { |
| if (null == dimensionRawColumnChunks[projectionListDimensionIndex]) { |
| dimensionRawColumnChunks[projectionListDimensionIndex] = |
| rawBlockletColumnChunks.getDataBlock().readDimensionChunk( |
| fileReader, projectionListDimensionIndex); |
| } |
| } |
| totalReadTime += System.currentTimeMillis() - filterDimensionReadTime; |
| |
| DimensionColumnPage[][] dimensionColumnPages = |
| new DimensionColumnPage[numDimensionChunks][numPages]; |
| MeasureRawColumnChunk[] measureRawColumnChunks = |
| new MeasureRawColumnChunk[blockExecutionInfo.getTotalNumberOfMeasureToRead()]; |
| int numMeasureChunks = measureRawColumnChunks.length; |
| |
| // read the measure chunk blocks which is not present |
| for (int chunkIndex = 0; chunkIndex < numMeasureChunks; chunkIndex++) { |
| if (null != rawBlockletColumnChunks.getMeasureRawColumnChunks()[chunkIndex]) { |
| measureRawColumnChunks[chunkIndex] = |
| rawBlockletColumnChunks.getMeasureRawColumnChunks()[chunkIndex]; |
| } |
| } |
| |
| long measureReadTime = System.currentTimeMillis(); |
| int[][] allSelectedMeasureColumnIndexRange = |
| blockExecutionInfo.getAllSelectedMeasureIndexRange(); |
| MeasureRawColumnChunk[] projectionListMeasureChunk = rawBlockletColumnChunks.getDataBlock() |
| .readMeasureChunks(fileReader, allSelectedMeasureColumnIndexRange); |
| measureReadTime = System.currentTimeMillis() - measureReadTime; |
| |
| for (int[] columnIndexRange : allSelectedMeasureColumnIndexRange) { |
| System.arraycopy(projectionListMeasureChunk, columnIndexRange[0], measureRawColumnChunks, |
| columnIndexRange[0], columnIndexRange[1] + 1 - columnIndexRange[0]); |
| } |
| /** |
| * Below code is to read the measure which is not read as part of filter or projection |
| * for example in case of or filter if first filter matches all the rows then it will not read |
| * second filter column and if it is present as part of projection, so needs to be read |
| */ |
| long filterMeasureReadTime = System.currentTimeMillis(); |
| int[] projectionListMeasureIndexes = blockExecutionInfo.getProjectionListMeasureIndexes(); |
| for (int projectionListMeasureIndex : projectionListMeasureIndexes) { |
| if (null == measureRawColumnChunks[projectionListMeasureIndex]) { |
| measureRawColumnChunks[projectionListMeasureIndex] = rawBlockletColumnChunks.getDataBlock() |
| .readMeasureChunk(fileReader, projectionListMeasureIndex); |
| } |
| } |
| measureReadTime += System.currentTimeMillis() - filterMeasureReadTime; |
| totalReadTime += measureReadTime; |
| ColumnPage[][] measureColumnPages = new ColumnPage[numMeasureChunks][numPages]; |
| scannedResult.setDimensionColumnPages(dimensionColumnPages); |
| scannedResult.setPageFilteredRowId(pageFilteredRowId); |
| scannedResult.setMeasureColumnPages(measureColumnPages); |
| scannedResult.setDimRawColumnChunks(dimensionRawColumnChunks); |
| scannedResult.setMsrRawColumnChunks(measureRawColumnChunks); |
| scannedResult.setPageFilteredRowCount(pageFilteredRowCount); |
| scannedResult.fillDataChunks(); |
| // adding statistics for carbon scan time |
| QueryStatistic scanTime = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.SCAN_BLOCKlET_TIME); |
| scanTime.addCountStatistic(QueryStatisticsConstants.SCAN_BLOCKlET_TIME, |
| scanTime.getCount() + (System.currentTimeMillis() - startTime - totalReadTime)); |
| QueryStatistic readTime = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.READ_BLOCKlET_TIME); |
| readTime.addCountStatistic(QueryStatisticsConstants.READ_BLOCKlET_TIME, |
| readTime.getCount() + totalReadTime); |
| return scannedResult; |
| } |
| |
| /** |
| * This method will process the data in below order |
| * 1. first apply min max on the filter tree and check whether any of the filter |
| * is fall on the range of min max, if not then return empty result |
| * 2. If filter falls on min max range then apply filter on actual |
| * data and get the pruned pages. |
| * 3. if pruned pages are not empty then read only those blocks(measure or dimension) |
| * which was present in the query but not present in the filter, as while applying filter |
| * some of the blocks where already read and present in chunk holder so not need to |
| * read those blocks again, this is to avoid reading of same blocks which was already read |
| * 4. Set the blocks and filter pages to scanned result |
| * |
| * @param rawBlockletColumnChunks blocklet raw chunk of all columns |
| * @throws FilterUnsupportedException |
| */ |
| private BlockletScannedResult executeFilterForPages( |
| RawBlockletColumnChunks rawBlockletColumnChunks) |
| throws FilterUnsupportedException, IOException { |
| long startTime = System.currentTimeMillis(); |
| // apply filter on actual data, for each page |
| BitSet pages = this.filterExecutor.prunePages(rawBlockletColumnChunks); |
| // if filter result is empty then return with empty result |
| if (pages.isEmpty()) { |
| CarbonUtil.freeMemory(rawBlockletColumnChunks.getDimensionRawColumnChunks(), |
| rawBlockletColumnChunks.getMeasureRawColumnChunks()); |
| |
| QueryStatistic scanTime = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.SCAN_BLOCKlET_TIME); |
| scanTime.addCountStatistic(QueryStatisticsConstants.SCAN_BLOCKlET_TIME, |
| scanTime.getCount() + (System.currentTimeMillis() - startTime)); |
| |
| QueryStatistic scannedBlocklets = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.BLOCKLET_SCANNED_NUM); |
| scannedBlocklets.addCountStatistic(QueryStatisticsConstants.BLOCKLET_SCANNED_NUM, |
| scannedBlocklets.getCount() + 1); |
| |
| QueryStatistic scannedPages = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.PAGE_SCANNED); |
| scannedPages |
| .addCountStatistic(QueryStatisticsConstants.PAGE_SCANNED, scannedPages.getCount()); |
| return createEmptyResult(); |
| } |
| |
| BlockletScannedResult scannedResult = |
| new FilterQueryScannedResult(blockExecutionInfo, queryStatisticsModel); |
| |
| // valid scanned blocklet |
| QueryStatistic validScannedBlockletStatistic = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.VALID_SCAN_BLOCKLET_NUM); |
| validScannedBlockletStatistic |
| .addCountStatistic(QueryStatisticsConstants.VALID_SCAN_BLOCKLET_NUM, |
| validScannedBlockletStatistic.getCount() + 1); |
| // adding statistics for valid number of pages |
| QueryStatistic validPages = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.VALID_PAGE_SCANNED); |
| validPages.addCountStatistic(QueryStatisticsConstants.VALID_PAGE_SCANNED, |
| validPages.getCount() + pages.cardinality()); |
| |
| QueryStatistic scannedBlocklets = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.BLOCKLET_SCANNED_NUM); |
| scannedBlocklets.addCountStatistic(QueryStatisticsConstants.BLOCKLET_SCANNED_NUM, |
| scannedBlocklets.getCount() + 1); |
| |
| QueryStatistic scannedPages = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.PAGE_SCANNED); |
| scannedPages.addCountStatistic(QueryStatisticsConstants.PAGE_SCANNED, |
| scannedPages.getCount() + pages.cardinality()); |
| // get the row indexes from bit set for each page |
| int[] pageFilteredPages = new int[pages.cardinality()]; |
| int[] numberOfRows = new int[pages.cardinality()]; |
| int index = 0; |
| for (int i = pages.nextSetBit(0); i >= 0; i = pages.nextSetBit(i + 1)) { |
| pageFilteredPages[index] = i; |
| numberOfRows[index++] = rawBlockletColumnChunks.getDataBlock().getPageRowCount(i); |
| } |
| |
| DimensionRawColumnChunk[] dimensionRawColumnChunks = |
| new DimensionRawColumnChunk[blockExecutionInfo.getTotalNumberDimensionToRead()]; |
| MeasureRawColumnChunk[] measureRawColumnChunks = |
| new MeasureRawColumnChunk[blockExecutionInfo.getTotalNumberOfMeasureToRead()]; |
| int numDimensionChunks = dimensionRawColumnChunks.length; |
| int numMeasureChunks = measureRawColumnChunks.length; |
| // read dimension chunk blocks from file which is not present |
| for (int chunkIndex = 0; chunkIndex < numDimensionChunks; chunkIndex++) { |
| dimensionRawColumnChunks[chunkIndex] = |
| rawBlockletColumnChunks.getDimensionRawColumnChunks()[chunkIndex]; |
| } |
| |
| // read the measure chunk blocks which is not present |
| for (int chunkIndex = 0; chunkIndex < numMeasureChunks; chunkIndex++) { |
| if (null != rawBlockletColumnChunks.getMeasureRawColumnChunks()[chunkIndex]) { |
| measureRawColumnChunks[chunkIndex] = |
| rawBlockletColumnChunks.getMeasureRawColumnChunks()[chunkIndex]; |
| } |
| } |
| |
| LazyBlockletLoader lazyBlocklet = |
| new LazyBlockletLoader(rawBlockletColumnChunks, blockExecutionInfo, |
| dimensionRawColumnChunks, measureRawColumnChunks, queryStatisticsModel); |
| DimensionColumnPage[][] dimensionColumnPages = |
| new DimensionColumnPage[numDimensionChunks][pages.cardinality()]; |
| ColumnPage[][] measureColumnPages = new ColumnPage[numMeasureChunks][pages.cardinality()]; |
| scannedResult.setDimensionColumnPages(dimensionColumnPages); |
| scannedResult.setMeasureColumnPages(measureColumnPages); |
| scannedResult.setDimRawColumnChunks(dimensionRawColumnChunks); |
| scannedResult.setMsrRawColumnChunks(measureRawColumnChunks); |
| scannedResult.setPageFilteredRowCount(numberOfRows); |
| scannedResult.setPageIdFiltered(pageFilteredPages); |
| scannedResult.setLazyBlockletLoader(lazyBlocklet); |
| scannedResult.setBlockletId(blockExecutionInfo.getBlockIdString(), |
| String.valueOf(rawBlockletColumnChunks.getDataBlock().blockletIndex())); |
| // adding statistics for carbon scan time |
| QueryStatistic scanTime = queryStatisticsModel.getStatisticsTypeAndObjMap() |
| .get(QueryStatisticsConstants.SCAN_BLOCKlET_TIME); |
| scanTime.addCountStatistic(QueryStatisticsConstants.SCAN_BLOCKlET_TIME, |
| scanTime.getCount() + (System.currentTimeMillis() - startTime)); |
| |
| return scannedResult; |
| } |
| } |