KYLIN-2622 Add SegmentAppendTrieDictBuilder for count distinct measure
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/8de0d529 Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/8de0d529 Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/8de0d529 Branch: refs/heads/2622-2764 Commit: 8de0d529723eca45fb2aeca5789a5d8f8dc8edb6 Parents: 520f627 Author: kangkaisen <kangkai...@live.com> Authored: Tue May 16 17:04:55 2017 +0800 Committer: kangkaisen <kangkai...@meituan.com> Committed: Mon Sep 4 21:38:46 2017 +0800 ---------------------------------------------------------------------- .../apache/kylin/dict/AppendTrieDictionary.java | 9 ++- .../apache/kylin/dict/DictionaryManager.java | 10 +++ .../kylin/dict/GlobalDictionaryBuilder.java | 8 +-- .../global/AppendTrieDictionaryBuilder.java | 15 ++-- .../kylin/dict/global/GlobalDictHDFSStore.java | 54 +++++++++----- .../kylin/dict/global/GlobalDictMetadata.java | 1 - .../kylin/dict/global/GlobalDictStore.java | 5 +- .../global/SegmentAppendTrieDictBuilder.java | 76 ++++++++++++++++++++ .../dict/global/AppendTrieDictionaryTest.java | 3 +- .../kylin/measure/bitmap/BitmapMeasureType.java | 21 +----- .../localmeta/cube_desc/ci_inner_join_cube.json | 2 +- webapp/app/js/model/cubeConfig.js | 3 +- .../cubeDesigner/advanced_settings.html | 13 +++- 13 files changed, 162 insertions(+), 58 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/core-dictionary/src/main/java/org/apache/kylin/dict/AppendTrieDictionary.java ---------------------------------------------------------------------- diff --git a/core-dictionary/src/main/java/org/apache/kylin/dict/AppendTrieDictionary.java b/core-dictionary/src/main/java/org/apache/kylin/dict/AppendTrieDictionary.java index b9f0d2b..18795b4 100644 --- a/core-dictionary/src/main/java/org/apache/kylin/dict/AppendTrieDictionary.java +++ b/core-dictionary/src/main/java/org/apache/kylin/dict/AppendTrieDictionary.java @@ -38,8 +38,8 @@ import java.io.IOException; import java.io.PrintStream; import java.util.Arrays; import java.util.Objects; +import java.util.TreeMap; import java.util.concurrent.ExecutionException; -import static com.google.common.base.Preconditions.checkState; /** * A dictionary based on Trie data structure that maps enumerations of byte[] to @@ -72,7 +72,12 @@ public class AppendTrieDictionary<T> extends CacheDictionary<T> { this.baseDir = baseDir; final GlobalDictStore globalDictStore = new GlobalDictHDFSStore(baseDir); Long[] versions = globalDictStore.listAllVersions(); - checkState(versions.length > 0, "Global dict at %s is empty", baseDir); + + if (versions.length == 0) { + this.metadata = new GlobalDictMetadata(0, 0, 0, 0, null, new TreeMap<AppendDictSliceKey, String>()); + return; // for the removed SegmentAppendTrieDictBuilder + } + final long latestVersion = versions[versions.length - 1]; final Path latestVersionPath = globalDictStore.getVersionDir(latestVersion); this.metadata = globalDictStore.getMetadata(latestVersion); http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/core-dictionary/src/main/java/org/apache/kylin/dict/DictionaryManager.java ---------------------------------------------------------------------- diff --git a/core-dictionary/src/main/java/org/apache/kylin/dict/DictionaryManager.java b/core-dictionary/src/main/java/org/apache/kylin/dict/DictionaryManager.java index 857ee30..47e5c29 100644 --- a/core-dictionary/src/main/java/org/apache/kylin/dict/DictionaryManager.java +++ b/core-dictionary/src/main/java/org/apache/kylin/dict/DictionaryManager.java @@ -227,6 +227,16 @@ public class DictionaryManager { if (dicts.size() == 1) return dicts.get(0); + /** + * AppendTrieDictionary needn't merge + * more than one AppendTrieDictionary will generate when user use {@link SegmentAppendTrieDictBuilder} + */ + for (DictionaryInfo dict: dicts) { + if (dict.getDictionaryClass().equals(AppendTrieDictionary.class.getName())) { + return dict; + } + } + DictionaryInfo firstDictInfo = null; int totalSize = 0; for (DictionaryInfo info : dicts) { http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/core-dictionary/src/main/java/org/apache/kylin/dict/GlobalDictionaryBuilder.java ---------------------------------------------------------------------- diff --git a/core-dictionary/src/main/java/org/apache/kylin/dict/GlobalDictionaryBuilder.java b/core-dictionary/src/main/java/org/apache/kylin/dict/GlobalDictionaryBuilder.java index a593371..404d53c 100644 --- a/core-dictionary/src/main/java/org/apache/kylin/dict/GlobalDictionaryBuilder.java +++ b/core-dictionary/src/main/java/org/apache/kylin/dict/GlobalDictionaryBuilder.java @@ -44,16 +44,13 @@ public class GlobalDictionaryBuilder implements IDictionaryBuilder { @Override public void init(DictionaryInfo dictInfo, int baseId) throws IOException { - if (dictInfo == null) { - throw new IllegalArgumentException("GlobalDictinaryBuilder must used with an existing DictionaryInfo"); - } - sourceColumn = dictInfo.getSourceTable() + "_" + dictInfo.getSourceColumn(); lock = KylinConfig.getInstanceFromEnv().getDistributedLockFactory().lockForCurrentThread(); lock.lock(getLockPath(sourceColumn), Long.MAX_VALUE); int maxEntriesPerSlice = KylinConfig.getInstanceFromEnv().getAppendDictEntrySize(); - this.builder = new AppendTrieDictionaryBuilder(dictInfo.getResourceDir(), maxEntriesPerSlice); + String baseDir = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory() + "resources/GlobalDict" + dictInfo.getResourceDir() + "/"; + this.builder = new AppendTrieDictionaryBuilder(baseDir, maxEntriesPerSlice, true); this.baseId = baseId; } @@ -96,5 +93,4 @@ public class GlobalDictionaryBuilder implements IDictionaryBuilder { private String getLockPath(String pathName) { return "/dict/" + pathName + "/lock"; } - } http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/core-dictionary/src/main/java/org/apache/kylin/dict/global/AppendTrieDictionaryBuilder.java ---------------------------------------------------------------------- diff --git a/core-dictionary/src/main/java/org/apache/kylin/dict/global/AppendTrieDictionaryBuilder.java b/core-dictionary/src/main/java/org/apache/kylin/dict/global/AppendTrieDictionaryBuilder.java index 90d65b6..54978c2 100644 --- a/core-dictionary/src/main/java/org/apache/kylin/dict/global/AppendTrieDictionaryBuilder.java +++ b/core-dictionary/src/main/java/org/apache/kylin/dict/global/AppendTrieDictionaryBuilder.java @@ -18,7 +18,6 @@ package org.apache.kylin.dict.global; -import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.util.BytesUtil; import org.apache.kylin.dict.AppendTrieDictionary; import org.apache.kylin.dict.BytesConverter; @@ -35,6 +34,7 @@ public class AppendTrieDictionaryBuilder { private final String baseDir; private final String workingDir; private final int maxEntriesPerSlice; + private final boolean isAppendDictGlobal; private GlobalDictStore store; private int maxId; @@ -46,20 +46,21 @@ public class AppendTrieDictionaryBuilder { private AppendDictSliceKey curKey; private AppendDictNode curNode; - public AppendTrieDictionaryBuilder(String resourceDir, int maxEntriesPerSlice) throws IOException { - this.baseDir = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory() + "resources/GlobalDict" + resourceDir + "/"; - this.workingDir = this.baseDir + "/working"; + public AppendTrieDictionaryBuilder(String baseDir, int maxEntriesPerSlice, boolean isAppendDictGlobal) throws IOException { + this.baseDir = baseDir; + this.workingDir = baseDir + "working"; this.maxEntriesPerSlice = maxEntriesPerSlice; + this.isAppendDictGlobal = isAppendDictGlobal; init(); } public synchronized void init() throws IOException { this.store = new GlobalDictHDFSStore(baseDir); - store.prepareForWrite(workingDir); + store.prepareForWrite(workingDir, isAppendDictGlobal); Long[] versions = store.listAllVersions(); - if (versions.length == 0) { // build dict for the first time + if (versions.length == 0 || !isAppendDictGlobal) { // build dict for the first time this.maxId = 0; this.maxValueLength = 0; this.nValues = 0; @@ -122,7 +123,7 @@ public class AppendTrieDictionaryBuilder { } GlobalDictMetadata metadata = new GlobalDictMetadata(baseId, this.maxId, this.maxValueLength, this.nValues, this.bytesConverter, sliceFileMap); - store.commit(workingDir, metadata); + store.commit(workingDir, metadata, isAppendDictGlobal); AppendTrieDictionary dict = new AppendTrieDictionary(); dict.init(this.baseDir); http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictHDFSStore.java ---------------------------------------------------------------------- diff --git a/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictHDFSStore.java b/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictHDFSStore.java index b30d5b9..4c8ce0f 100644 --- a/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictHDFSStore.java +++ b/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictHDFSStore.java @@ -59,13 +59,6 @@ public class GlobalDictHDFSStore extends GlobalDictStore { this.basePath = new Path(baseDir); this.conf = HadoopUtil.getCurrentConfiguration(); this.fileSystem = HadoopUtil.getFileSystem(baseDir); - - if (!fileSystem.exists(basePath)) { - logger.info("Global dict at {} doesn't exist, create a new one", basePath); - fileSystem.mkdirs(basePath); - } - - migrateOldLayout(); } // Previously we put slice files and index file directly in base directory, @@ -111,8 +104,15 @@ public class GlobalDictHDFSStore extends GlobalDictStore { } @Override - void prepareForWrite(String workingDir) throws IOException { - // TODO create lock file + void prepareForWrite(String workingDir, boolean isGlobal) throws IOException { + if (!fileSystem.exists(basePath)) { + logger.info("Global dict at {} doesn't exist, create a new one", basePath); + fileSystem.mkdirs(basePath); + } + + migrateOldLayout(); + + logger.info("Prepare to write Global dict at {}, isGlobal={}", workingDir, isGlobal); Path working = new Path(workingDir); if (fileSystem.exists(working)) { @@ -122,7 +122,7 @@ public class GlobalDictHDFSStore extends GlobalDictStore { // when build dict, copy all data into working dir and work on it, avoiding suddenly server crash made data corrupt Long[] versions = listAllVersions(); - if (versions.length > 0) { + if (versions.length > 0 && isGlobal) { Path latestVersion = getVersionDir(versions[versions.length - 1]); FileUtil.copy(fileSystem, latestVersion, fileSystem, working, false, true, conf); } else { @@ -132,6 +132,10 @@ public class GlobalDictHDFSStore extends GlobalDictStore { @Override public Long[] listAllVersions() throws IOException { + if (!fileSystem.exists(basePath)) { + return new Long[0]; // for the removed SegmentAppendTrieDictBuilder + } + FileStatus[] versionDirs = fileSystem.listStatus(basePath, new PathFilter() { @Override public boolean accept(Path path) { @@ -208,7 +212,7 @@ public class GlobalDictHDFSStore extends GlobalDictStore { } @Override - public void commit(String workingDir, GlobalDictMetadata metadata) throws IOException { + public void commit(String workingDir, GlobalDictMetadata metadata, boolean isAppendDictGlobal) throws IOException { Path workingPath = new Path(workingDir); // delete v1 index file @@ -225,22 +229,38 @@ public class GlobalDictHDFSStore extends GlobalDictStore { Path newVersionPath = new Path(basePath, VERSION_PREFIX + System.currentTimeMillis()); fileSystem.rename(workingPath, newVersionPath); - cleanUp(); + cleanUp(isAppendDictGlobal); } // Check versions count, delete expired versions - private void cleanUp() throws IOException { - Long[] versions = listAllVersions(); + private void cleanUp(boolean isAppendDictGlobal) throws IOException { long timestamp = System.currentTimeMillis(); - for (int i = 0; i < versions.length - maxVersions; i++) { - if (versions[i] + versionTTL < timestamp) { - fileSystem.delete(getVersionDir(versions[i]), true); + if (isAppendDictGlobal) { + Long[] versions = listAllVersions(); + for (int i = 0; i < versions.length - maxVersions; i++) { + if (versions[i] + versionTTL < timestamp) { + fileSystem.delete(getVersionDir(versions[i]), true); + } + } + } else { + FileStatus[] segmentDictDirs = fileSystem.listStatus(basePath.getParent()); + for (FileStatus fileStatus : segmentDictDirs) { + String filePath = fileStatus.getPath().getName(); + Long version = Long.parseLong(filePath.split("_")[1]); + if (version + versionTTL < timestamp) { + fileSystem.delete(new Path(basePath.getParent() + "/" + filePath), true); + } } } } @Override public String copyToAnotherMeta(KylinConfig srcConfig, KylinConfig dstConfig) throws IOException { + if (baseDir.contains("resources/SegmentDict")) { + logger.info("SegmentAppendTrieDict needn't to copy"); + return baseDir; + } + checkArgument(baseDir.startsWith(srcConfig.getHdfsWorkingDirectory()), "Please check why current directory {} doesn't belong to source working directory {}", baseDir, srcConfig.getHdfsWorkingDirectory()); final String dstBaseDir = baseDir.replaceFirst(srcConfig.getHdfsWorkingDirectory(), dstConfig.getHdfsWorkingDirectory()); http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictMetadata.java ---------------------------------------------------------------------- diff --git a/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictMetadata.java b/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictMetadata.java index 7c89ea2..7fe6b60 100644 --- a/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictMetadata.java +++ b/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictMetadata.java @@ -38,7 +38,6 @@ public class GlobalDictMetadata { public GlobalDictMetadata(int baseId, int maxId, int maxValueLength, int nValues, BytesConverter bytesConverter, NavigableMap<AppendDictSliceKey, String> sliceFileMap) { - Preconditions.checkNotNull(bytesConverter, "bytesConverter"); Preconditions.checkNotNull(sliceFileMap, "sliceFileMap"); this.baseId = baseId; http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictStore.java ---------------------------------------------------------------------- diff --git a/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictStore.java b/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictStore.java index eaf0729..f686680 100644 --- a/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictStore.java +++ b/core-dictionary/src/main/java/org/apache/kylin/dict/global/GlobalDictStore.java @@ -37,7 +37,7 @@ public abstract class GlobalDictStore { } // workingDir should be an absolute path, will create if not exists - abstract void prepareForWrite(String workingDir) throws IOException; + abstract void prepareForWrite(String workingDir, boolean isGlobal) throws IOException; /** * @return all versions of this dictionary in ascending order @@ -87,9 +87,10 @@ public abstract class GlobalDictStore { * commit the <i>DictSlice</i> and <i>GlobalDictMetadata</i> in workingDir to new versionDir * @param workingDir where store the tmp slice and index, should exist * @param globalDictMetadata the metadata of global dict + * @param isAppendDictGlobal mark the append dict whether is global or not * @throws IOException on I/O error */ - public abstract void commit(String workingDir, GlobalDictMetadata globalDictMetadata) throws IOException; + public abstract void commit(String workingDir, GlobalDictMetadata globalDictMetadata, boolean isAppendDictGlobal) throws IOException; /** * Copy the latest version of this dict to another meta. The source is unchanged. http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/core-dictionary/src/main/java/org/apache/kylin/dict/global/SegmentAppendTrieDictBuilder.java ---------------------------------------------------------------------- diff --git a/core-dictionary/src/main/java/org/apache/kylin/dict/global/SegmentAppendTrieDictBuilder.java b/core-dictionary/src/main/java/org/apache/kylin/dict/global/SegmentAppendTrieDictBuilder.java new file mode 100644 index 0000000..270deee --- /dev/null +++ b/core-dictionary/src/main/java/org/apache/kylin/dict/global/SegmentAppendTrieDictBuilder.java @@ -0,0 +1,76 @@ +/* + * 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.kylin.dict.global; + +import org.apache.kylin.common.KylinConfig; +import org.apache.kylin.common.util.Dictionary; +import org.apache.kylin.dict.DictionaryInfo; +import org.apache.kylin.dict.IDictionaryBuilder; + +import java.io.IOException; +import java.util.UUID; + +/** + * SegmentAppendTrieDictBuilder based on one segment. + * SegmentAppendTrieDictBuilder only used for count distinct measure that needn't rollup among segments. + * SegmentAppendTrieDictBuilder could avoid AppendTrieDictionary infinite growth. + * SegmentAppendTrieDictBuilder doesn't support merge. + */ +public class SegmentAppendTrieDictBuilder implements IDictionaryBuilder { + private AppendTrieDictionaryBuilder builder; + private int baseId; + private String sourceColumn; + + @Override + public void init(DictionaryInfo dictInfo, int baseId) throws IOException { + sourceColumn = dictInfo.getSourceTable() + "." + dictInfo.getSourceColumn(); + + int maxEntriesPerSlice = KylinConfig.getInstanceFromEnv().getAppendDictEntrySize(); + if (hdfsDir == null) { + //build in Kylin job server + hdfsDir = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory(); + } + //use UUID to make each segment dict in different HDFS dir and support concurrent build + //use timestamp to make the segment dict easily to delete + String baseDir = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory() + "resources/SegmentDict" + dictInfo.getResourceDir() + "/" + UUID.randomUUID().toString() + "_" + System.currentTimeMillis()+ "/"; + + this.builder = new AppendTrieDictionaryBuilder(baseDir, maxEntriesPerSlice, false); + this.baseId = baseId; + } + + @Override + public boolean addValue(String value) { + if (value == null) { + return false; + } + + try { + builder.addValue(value); + } catch (Throwable e) { + throw new RuntimeException(String.format("Failed to create global dictionary on %s ", sourceColumn), e); + } + + return true; + } + + @Override + public Dictionary<String> build() throws IOException { + return builder.build(baseId); + } +} http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/core-dictionary/src/test/java/org/apache/kylin/dict/global/AppendTrieDictionaryTest.java ---------------------------------------------------------------------- diff --git a/core-dictionary/src/test/java/org/apache/kylin/dict/global/AppendTrieDictionaryTest.java b/core-dictionary/src/test/java/org/apache/kylin/dict/global/AppendTrieDictionaryTest.java index 47011fe..6b39c36 100644 --- a/core-dictionary/src/test/java/org/apache/kylin/dict/global/AppendTrieDictionaryTest.java +++ b/core-dictionary/src/test/java/org/apache/kylin/dict/global/AppendTrieDictionaryTest.java @@ -94,7 +94,8 @@ public class AppendTrieDictionaryTest extends LocalFileMetadataTestCase { private AppendTrieDictionaryBuilder createBuilder(String resourceDir) throws IOException { int maxEntriesPerSlice = KylinConfig.getInstanceFromEnv().getAppendDictEntrySize(); - return new AppendTrieDictionaryBuilder(resourceDir, maxEntriesPerSlice); + String baseDir = KylinConfig.getInstanceFromEnv().getHdfsWorkingDirectory() + "/resources/GlobalDict" + resourceDir + "/"; + return new AppendTrieDictionaryBuilder(baseDir, maxEntriesPerSlice, true); } @Test http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/core-metadata/src/main/java/org/apache/kylin/measure/bitmap/BitmapMeasureType.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/measure/bitmap/BitmapMeasureType.java b/core-metadata/src/main/java/org/apache/kylin/measure/bitmap/BitmapMeasureType.java index e4fb079..403d1b6 100644 --- a/core-metadata/src/main/java/org/apache/kylin/measure/bitmap/BitmapMeasureType.java +++ b/core-metadata/src/main/java/org/apache/kylin/measure/bitmap/BitmapMeasureType.java @@ -126,25 +126,8 @@ public class BitmapMeasureType extends MeasureType<BitmapCounter> { @Override public BitmapCounter reEncodeDictionary(BitmapCounter value, MeasureDesc measureDesc, Map<TblColRef, Dictionary<String>> oldDicts, Map<TblColRef, Dictionary<String>> newDicts) { - if (!needDictionaryColumn(measureDesc.getFunction())) { - return value; - } - TblColRef colRef = measureDesc.getFunction().getParameter().getColRefs().get(0); - Dictionary<String> sourceDict = oldDicts.get(colRef); - Dictionary<String> mergedDict = newDicts.get(colRef); - - BitmapCounter retValue = factory.newBitmap(); - for (int id : value) { - int newId; - String v = sourceDict.getValueFromId(id); - if (v == null) { - newId = mergedDict.nullId(); - } else { - newId = mergedDict.getIdFromValue(v); - } - retValue.add(newId); - } - return retValue; + //BitmapCounter needn't reEncode + return value; } @Override http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json ---------------------------------------------------------------------- diff --git a/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json b/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json index efed0f9..3b942d9 100644 --- a/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json +++ b/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json @@ -359,7 +359,7 @@ "dictionaries": [ { "column": "TEST_KYLIN_FACT.TEST_COUNT_DISTINCT_BITMAP", - "builder": "org.apache.kylin.dict.GlobalDictionaryBuilder" + "builder": "org.apache.kylin.dict.global.SegmentAppendTrieDictBuilder" } ], "rowkey": { http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/webapp/app/js/model/cubeConfig.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/model/cubeConfig.js b/webapp/app/js/model/cubeConfig.js index eec3f10..7caa19b 100644 --- a/webapp/app/js/model/cubeConfig.js +++ b/webapp/app/js/model/cubeConfig.js @@ -110,7 +110,8 @@ KylinApp.constant('cubeConfig', { ], statusNeedNofity:['ERROR', 'DISCARDED', 'SUCCEED'], buildDictionaries:[ - {name:"Global Dictionary", value:"org.apache.kylin.dict.GlobalDictionaryBuilder"} + {name:"Global Dictionary", value:"org.apache.kylin.dict.GlobalDictionaryBuilder"}, + {name:"Segment Dictionary", value:"org.apache.kylin.dict.global.SegmentAppendTrieDictBuilder"} ], needSetLengthEncodingList:['fixed_length','fixed_length_hex','int','integer'] }); http://git-wip-us.apache.org/repos/asf/kylin/blob/8de0d529/webapp/app/partials/cubeDesigner/advanced_settings.html ---------------------------------------------------------------------- diff --git a/webapp/app/partials/cubeDesigner/advanced_settings.html b/webapp/app/partials/cubeDesigner/advanced_settings.html index 8062975..8768108 100755 --- a/webapp/app/partials/cubeDesigner/advanced_settings.html +++ b/webapp/app/partials/cubeDesigner/advanced_settings.html @@ -534,7 +534,18 @@ </script> <script type="text/ng-template" id="AdvancedDictionariesTip.html"> <div> - <h4>Special settings for dictionaries. Leave blank by default.</h4> + <h4>Special settings for dictionaries.</h4> + <ol> + <li> + "Global Dictionary" is the default dict for precise count distinct measure, which support rollup among all segments. + </li> + <li> + "Segment Dictionary" is the special dict for precise count distinct measure, which is based on one segment and could not + support rollup among segments. + Specifically, if your cube isn't partitioned or you can ensure all your SQLs will group by your partition_column, + you could use "Segment Dictionary" instead of "Global Dictionary". + </li> + </ol> </div> </script>