You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by li...@apache.org on 2016/10/19 03:02:35 UTC

[48/50] [abbrv] kylin git commit: KYLIN-2105 add QueryId

KYLIN-2105 add QueryId


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/db09f5f9
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/db09f5f9
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/db09f5f9

Branch: refs/heads/master-hbase1.x
Commit: db09f5f9cae5a3d3ff731221cbb1c026da4f4e41
Parents: 6cafc42
Author: gaodayue <ga...@meituan.com>
Authored: Wed Oct 19 08:36:53 2016 +0800
Committer: gaodayue <ga...@meituan.com>
Committed: Wed Oct 19 08:36:53 2016 +0800

----------------------------------------------------------------------
 .../kylin/common/debug/BackdoorToggles.java     |   6 +
 .../apache/kylin/common/util/SetThreadName.java |  49 +++++
 .../apache/kylin/rest/service/QueryService.java |  32 ++-
 .../kylin/rest/util/QueryIdGenerator.java       |  45 +++++
 .../kylin/rest/util/QueryIdGeneratorTest.java   | 106 ++++++++++
 .../src/main/resources/applicationContext.xml   |   1 +
 .../hbase/cube/v2/CubeHBaseEndpointRPC.java     |   7 +-
 .../coprocessor/endpoint/CubeVisitService.java  |   4 +-
 .../endpoint/generated/CubeVisitProtos.java     | 197 +++++++++++++++++--
 .../endpoint/protobuf/CubeVisit.proto           |   1 +
 10 files changed, 420 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/db09f5f9/core-common/src/main/java/org/apache/kylin/common/debug/BackdoorToggles.java
----------------------------------------------------------------------
diff --git a/core-common/src/main/java/org/apache/kylin/common/debug/BackdoorToggles.java b/core-common/src/main/java/org/apache/kylin/common/debug/BackdoorToggles.java
index f88781a..f7c90aa 100644
--- a/core-common/src/main/java/org/apache/kylin/common/debug/BackdoorToggles.java
+++ b/core-common/src/main/java/org/apache/kylin/common/debug/BackdoorToggles.java
@@ -65,6 +65,10 @@ public class BackdoorToggles {
             return Integer.valueOf(v);
     }
 
+    public static String getQueryId() {
+        return getString(KEY_QUERY_ID);
+    }
+
     public static Pair<Short, Short> getShardAssignment() {
         String v = getString(DEBUG_TOGGLE_SHARD_ASSIGNMENT);
         if (v == null) {
@@ -92,6 +96,8 @@ public class BackdoorToggles {
         _backdoorToggles.remove();
     }
 
+    public final static String KEY_QUERY_ID = "QUERY_ID";
+
     /**
      * set DEBUG_TOGGLE_DISABLE_FUZZY_KEY=true to disable fuzzy key for debug/profile usage
      *

http://git-wip-us.apache.org/repos/asf/kylin/blob/db09f5f9/core-common/src/main/java/org/apache/kylin/common/util/SetThreadName.java
----------------------------------------------------------------------
diff --git a/core-common/src/main/java/org/apache/kylin/common/util/SetThreadName.java b/core-common/src/main/java/org/apache/kylin/common/util/SetThreadName.java
new file mode 100644
index 0000000..9e5197e
--- /dev/null
+++ b/core-common/src/main/java/org/apache/kylin/common/util/SetThreadName.java
@@ -0,0 +1,49 @@
+/*
+ * 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.common.util;
+
+import java.io.Closeable;
+
+/**
+ *
+ * An utility that makes it easy to change current thread name in a try-with-resource block.
+ *
+ * <p> Example:
+ *
+ * <pre>
+ *     // old thread name
+ *     try (SetThreadName ignored = new SetThreadName(format, arg1, arg2)) {
+ *         // new thread name
+ *     }
+ *     // old thread name
+ * </pre>
+ */
+public class SetThreadName implements Closeable {
+    private final String originThreadName;
+
+    public SetThreadName(String format, Object... args) {
+        originThreadName = Thread.currentThread().getName();
+        Thread.currentThread().setName(String.format(format, args) + "-" + Thread.currentThread().getId());
+    }
+
+    @Override
+    public void close() {
+        Thread.currentThread().setName(originThreadName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/db09f5f9/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java b/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
index a7ac4b6..2803125 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
@@ -55,6 +55,7 @@ import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.debug.BackdoorToggles;
 import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.common.util.DBUtils;
+import org.apache.kylin.common.util.SetThreadName;
 import org.apache.kylin.cube.CubeInstance;
 import org.apache.kylin.cube.CubeManager;
 import org.apache.kylin.cube.cuboid.Cuboid;
@@ -71,6 +72,7 @@ import org.apache.kylin.rest.model.TableMeta;
 import org.apache.kylin.rest.request.PrepareSqlRequest;
 import org.apache.kylin.rest.request.SQLRequest;
 import org.apache.kylin.rest.response.SQLResponse;
+import org.apache.kylin.rest.util.QueryIdGenerator;
 import org.apache.kylin.rest.util.QueryUtil;
 import org.apache.kylin.rest.util.Serializer;
 import org.apache.kylin.storage.exception.ScanOutOfLimitException;
@@ -112,10 +114,12 @@ public class QueryService extends BasicService {
     private final BadQueryDetector badQueryDetector = new BadQueryDetector();
 
     private final String hbaseUrl;
-    private final String tableNameBase;
     private final String userTableName;
 
     @Autowired
+    private QueryIdGenerator queryIdGenerator;
+
+    @Autowired
     private CacheManager cacheManager;
 
     @Autowired
@@ -130,7 +134,7 @@ public class QueryService extends BasicService {
         String metadataUrl = KylinConfig.getInstanceFromEnv().getMetadataUrl();
         // split TABLE@HBASE_URL
         int cut = metadataUrl.indexOf('@');
-        tableNameBase = cut < 0 ? DEFAULT_TABLE_PREFIX : metadataUrl.substring(0, cut);
+        String tableNameBase = cut < 0 ? DEFAULT_TABLE_PREFIX : metadataUrl.substring(0, cut);
         hbaseUrl = cut < 0 ? metadataUrl : metadataUrl.substring(cut + 1);
         userTableName = tableNameBase + USER_TABLE_NAME;
 
@@ -264,6 +268,7 @@ public class QueryService extends BasicService {
         StringBuilder stringBuilder = new StringBuilder();
         stringBuilder.append(newLine);
         stringBuilder.append("==========================[QUERY]===============================").append(newLine);
+        stringBuilder.append("Query Id: ").append(BackdoorToggles.getQueryId()).append(newLine);
         stringBuilder.append("SQL: ").append(request.getSql()).append(newLine);
         stringBuilder.append("User: ").append(user).append(newLine);
         stringBuilder.append("Success: ").append((null == response.getExceptionMessage())).append(newLine);
@@ -314,20 +319,27 @@ public class QueryService extends BasicService {
     }
 
     public SQLResponse doQueryWithCache(SQLRequest sqlRequest) {
-        try {
-            BackdoorToggles.setToggles(sqlRequest.getBackdoorToggles());
+        KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
+        String serverMode = kylinConfig.getServerMode();
+        if (!(Constant.SERVER_MODE_QUERY.equals(serverMode.toLowerCase()) || Constant.SERVER_MODE_ALL.equals(serverMode.toLowerCase()))) {
+            throw new InternalErrorException("Query is not allowed in " + serverMode + " mode.");
+        }
+
+        final String queryId = queryIdGenerator.nextId(sqlRequest.getProject());
 
+        Map<String, String> toggles = new HashMap<>();
+        toggles.put(BackdoorToggles.KEY_QUERY_ID, queryId);
+        if (sqlRequest.getBackdoorToggles() != null) {
+            toggles.putAll(sqlRequest.getBackdoorToggles());
+        }
+        BackdoorToggles.setToggles(toggles);
+
+        try (SetThreadName ignored = new SetThreadName("Query-%s", queryId)) {
             String sql = sqlRequest.getSql();
             String project = sqlRequest.getProject();
             logger.info("Using project: " + project);
             logger.info("The original query:  " + sql);
 
-            KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
-            String serverMode = kylinConfig.getServerMode();
-            if (!(Constant.SERVER_MODE_QUERY.equals(serverMode.toLowerCase()) || Constant.SERVER_MODE_ALL.equals(serverMode.toLowerCase()))) {
-                throw new InternalErrorException("Query is not allowed in " + serverMode + " mode.");
-            }
-
             if (!sql.toLowerCase().contains("select")) {
                 logger.debug("Directly return exception as not supported");
                 throw new InternalErrorException("Not Supported SQL.");

http://git-wip-us.apache.org/repos/asf/kylin/blob/db09f5f9/server-base/src/main/java/org/apache/kylin/rest/util/QueryIdGenerator.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/util/QueryIdGenerator.java b/server-base/src/main/java/org/apache/kylin/rest/util/QueryIdGenerator.java
new file mode 100644
index 0000000..d9913e4
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/util/QueryIdGenerator.java
@@ -0,0 +1,45 @@
+/*
+ * 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.rest.util;
+
+import org.apache.commons.lang3.time.FastDateFormat;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+import java.util.concurrent.ThreadLocalRandom;
+
+@ThreadSafe
+public class QueryIdGenerator {
+    private static final char[] base26 = "abcdefghijklmnopqrstuvwxyz".toCharArray();
+    private static final FastDateFormat dateFormat = FastDateFormat.getInstance("yyyyMMdd_HHmmss");
+
+    /**
+     * @param project name of the project
+     * @return the next query id. We try to generate unique id as much as possible, but don't guarantee it.
+     */
+    @Nonnull
+    public String nextId(final String project) {
+        char[] postfix = new char[6];
+        for (int i = 0; i < postfix.length; i++) {
+            postfix[i] = base26[ThreadLocalRandom.current().nextInt(base26.length)];
+        }
+
+        return String.format("%s_%s_%s", dateFormat.format(System.currentTimeMillis()), project, new String(postfix));
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/db09f5f9/server-base/src/test/java/org/apache/kylin/rest/util/QueryIdGeneratorTest.java
----------------------------------------------------------------------
diff --git a/server-base/src/test/java/org/apache/kylin/rest/util/QueryIdGeneratorTest.java b/server-base/src/test/java/org/apache/kylin/rest/util/QueryIdGeneratorTest.java
new file mode 100644
index 0000000..1085206
--- /dev/null
+++ b/server-base/src/test/java/org/apache/kylin/rest/util/QueryIdGeneratorTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.rest.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+public class QueryIdGeneratorTest {
+
+    @Test
+    public void testIdFormat() {
+        QueryIdGenerator generator = new QueryIdGenerator();
+        for (int i = 0; i < 100; i++) {
+            String queryId = generator.nextId("project");
+            Assert.assertTrue(queryId.contains("project"));
+        }
+    }
+
+    @Test
+    public void testIdUniqueness() {
+        QueryIdGenerator generator = new QueryIdGenerator();
+        Set<String> idSet = new HashSet<>();
+
+        for (int i = 0; i < 1000; i++) {
+            idSet.add(generator.nextId("test"));
+        }
+
+        Assert.assertEquals(1000, idSet.size());
+    }
+
+    @Test
+    public void testSingleThreadThroughput() {
+        int N = 1_000_000;
+        long millis = new GenIdTask(new QueryIdGenerator(), N).call();
+
+        // ops / second
+        double throughput = (N * 1000.0) / millis;
+        System.out.format("QueryIdGenerator single thread throughput: %d ops/second\n", (int) throughput);
+    }
+
+    @Test
+    public void testMultiThreadsThroughput() throws ExecutionException, InterruptedException {
+        QueryIdGenerator generator = new QueryIdGenerator();
+        int N = 1_000_000;
+
+        final int numThreads = 4;
+        ExecutorService pool = Executors.newFixedThreadPool(numThreads);
+        Future[] futures = new Future[numThreads];
+
+        for (int i = 0; i < numThreads; i++) {
+            futures[i] = pool.submit(new GenIdTask(generator, N));
+        }
+
+        long sumMillis = 0;
+        for (int i = 0; i < numThreads; i++) {
+            sumMillis += (long) futures[i].get();
+        }
+        pool.shutdown();
+
+        double avgThroughputPerThread = (N * 1000.0) / (sumMillis / (double) numThreads);
+        System.out.format("QueryIdGenerator multi threads throughput: %d ops/second\n", (int) avgThroughputPerThread);
+    }
+
+    private static class GenIdTask implements Callable<Long> {
+        private final QueryIdGenerator generator;
+        private final int N;
+
+        GenIdTask(QueryIdGenerator generator, int N) {
+            this.generator = generator;
+            this.N = N;
+        }
+
+        @Override
+        public Long call() {
+            long start = System.currentTimeMillis();
+            for (int i = 0; i < N; i++) {
+                generator.nextId("test");
+            }
+            return System.currentTimeMillis() - start;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/kylin/blob/db09f5f9/server/src/main/resources/applicationContext.xml
----------------------------------------------------------------------
diff --git a/server/src/main/resources/applicationContext.xml b/server/src/main/resources/applicationContext.xml
index 081dc53..c8a4e54 100644
--- a/server/src/main/resources/applicationContext.xml
+++ b/server/src/main/resources/applicationContext.xml
@@ -39,6 +39,7 @@
     <aop:aspectj-autoproxy/>
 
     <bean class="org.apache.kylin.rest.init.InitialTaskManager" />
+    <bean class="org.apache.kylin.rest.util.QueryIdGenerator" />
 
     <context:component-scan base-package="org.apache.kylin.rest"/>
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/db09f5f9/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseEndpointRPC.java
----------------------------------------------------------------------
diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseEndpointRPC.java b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseEndpointRPC.java
index f285153..4f538ae 100644
--- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseEndpointRPC.java
+++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/CubeHBaseEndpointRPC.java
@@ -32,6 +32,7 @@ import org.apache.hadoop.hbase.client.coprocessor.Batch;
 import org.apache.hadoop.hbase.ipc.BlockingRpcCallback;
 import org.apache.hadoop.hbase.ipc.ServerRpcController;
 import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.debug.BackdoorToggles;
 import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.common.util.BytesSerializer;
 import org.apache.kylin.common.util.BytesUtil;
@@ -154,13 +155,17 @@ public class CubeHBaseEndpointRPC extends CubeHBaseRPC {
         }
         builder.setRowkeyPreambleSize(cubeSeg.getRowKeyPreambleSize());
         builder.setKylinProperties(kylinConfig.getConfigAsString());
+        final String queryId = BackdoorToggles.getQueryId();
+        if (queryId != null) {
+            builder.setQueryId(queryId);
+        }
 
         for (final Pair<byte[], byte[]> epRange : getEPKeyRanges(cuboidBaseShard, shardNum, totalShards)) {
             executorService.submit(new Runnable() {
                 @Override
                 public void run() {
 
-                    final String logHeader = "<sub-thread for GTScanRequest " + Integer.toHexString(System.identityHashCode(scanRequest)) + "> ";
+                    final String logHeader = String.format("<sub-thread for Query %s GTScanRequest %s>", queryId, Integer.toHexString(System.identityHashCode(scanRequest)));
                     final boolean[] abnormalFinish = new boolean[1];
 
                     try {

http://git-wip-us.apache.org/repos/asf/kylin/blob/db09f5f9/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/CubeVisitService.java
----------------------------------------------------------------------
diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/CubeVisitService.java b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/CubeVisitService.java
index 3d7b15e..506778c 100644
--- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/CubeVisitService.java
+++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/CubeVisitService.java
@@ -46,6 +46,7 @@ import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.util.Bytes;
 import org.apache.kylin.common.util.BytesUtil;
 import org.apache.kylin.common.util.CompressionUtils;
+import org.apache.kylin.common.util.SetThreadName;
 import org.apache.kylin.cube.kv.RowConstants;
 import org.apache.kylin.gridtable.GTRecord;
 import org.apache.kylin.gridtable.GTScanExceedThresholdException;
@@ -174,7 +175,8 @@ public class CubeVisitService extends CubeVisitProtos.CubeVisitService implement
         byte[] allRows;
         String debugGitTag = "";
 
-        try {
+        String queryId = request.hasQueryId() ? request.getQueryId() : "UnknownId";
+        try (SetThreadName ignored = new SetThreadName("Kylin Query-%s", queryId)) {
             this.serviceStartTime = System.currentTimeMillis();
 
             region = env.getRegion();

http://git-wip-us.apache.org/repos/asf/kylin/blob/db09f5f9/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/generated/CubeVisitProtos.java
----------------------------------------------------------------------
diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/generated/CubeVisitProtos.java b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/generated/CubeVisitProtos.java
index b0688b7..628d453 100644
--- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/generated/CubeVisitProtos.java
+++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/generated/CubeVisitProtos.java
@@ -92,6 +92,21 @@ public final class CubeVisitProtos {
      */
     com.google.protobuf.ByteString
         getKylinPropertiesBytes();
+
+    // optional string queryId = 6;
+    /**
+     * <code>optional string queryId = 6;</code>
+     */
+    boolean hasQueryId();
+    /**
+     * <code>optional string queryId = 6;</code>
+     */
+    java.lang.String getQueryId();
+    /**
+     * <code>optional string queryId = 6;</code>
+     */
+    com.google.protobuf.ByteString
+        getQueryIdBytes();
   }
   /**
    * Protobuf type {@code CubeVisitRequest}
@@ -172,6 +187,11 @@ public final class CubeVisitProtos {
               kylinProperties_ = input.readBytes();
               break;
             }
+            case 50: {
+              bitField0_ |= 0x00000010;
+              queryId_ = input.readBytes();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -858,12 +878,56 @@ public final class CubeVisitProtos {
       }
     }
 
+    // optional string queryId = 6;
+    public static final int QUERYID_FIELD_NUMBER = 6;
+    private java.lang.Object queryId_;
+    /**
+     * <code>optional string queryId = 6;</code>
+     */
+    public boolean hasQueryId() {
+      return ((bitField0_ & 0x00000010) == 0x00000010);
+    }
+    /**
+     * <code>optional string queryId = 6;</code>
+     */
+    public java.lang.String getQueryId() {
+      java.lang.Object ref = queryId_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          queryId_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string queryId = 6;</code>
+     */
+    public com.google.protobuf.ByteString
+        getQueryIdBytes() {
+      java.lang.Object ref = queryId_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        queryId_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
     private void initFields() {
       gtScanRequest_ = com.google.protobuf.ByteString.EMPTY;
       hbaseRawScan_ = com.google.protobuf.ByteString.EMPTY;
       rowkeyPreambleSize_ = 0;
       hbaseColumnsToGT_ = java.util.Collections.emptyList();
       kylinProperties_ = "";
+      queryId_ = "";
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -908,6 +972,9 @@ public final class CubeVisitProtos {
       if (((bitField0_ & 0x00000008) == 0x00000008)) {
         output.writeBytes(5, getKylinPropertiesBytes());
       }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        output.writeBytes(6, getQueryIdBytes());
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -937,6 +1004,10 @@ public final class CubeVisitProtos {
         size += com.google.protobuf.CodedOutputStream
           .computeBytesSize(5, getKylinPropertiesBytes());
       }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(6, getQueryIdBytes());
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -982,6 +1053,11 @@ public final class CubeVisitProtos {
         result = result && getKylinProperties()
             .equals(other.getKylinProperties());
       }
+      result = result && (hasQueryId() == other.hasQueryId());
+      if (hasQueryId()) {
+        result = result && getQueryId()
+            .equals(other.getQueryId());
+      }
       result = result &&
           getUnknownFields().equals(other.getUnknownFields());
       return result;
@@ -1015,6 +1091,10 @@ public final class CubeVisitProtos {
         hash = (37 * hash) + KYLINPROPERTIES_FIELD_NUMBER;
         hash = (53 * hash) + getKylinProperties().hashCode();
       }
+      if (hasQueryId()) {
+        hash = (37 * hash) + QUERYID_FIELD_NUMBER;
+        hash = (53 * hash) + getQueryId().hashCode();
+      }
       hash = (29 * hash) + getUnknownFields().hashCode();
       memoizedHashCode = hash;
       return hash;
@@ -1139,6 +1219,8 @@ public final class CubeVisitProtos {
         }
         kylinProperties_ = "";
         bitField0_ = (bitField0_ & ~0x00000010);
+        queryId_ = "";
+        bitField0_ = (bitField0_ & ~0x00000020);
         return this;
       }
 
@@ -1192,6 +1274,10 @@ public final class CubeVisitProtos {
           to_bitField0_ |= 0x00000008;
         }
         result.kylinProperties_ = kylinProperties_;
+        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+          to_bitField0_ |= 0x00000010;
+        }
+        result.queryId_ = queryId_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -1248,6 +1334,11 @@ public final class CubeVisitProtos {
           kylinProperties_ = other.kylinProperties_;
           onChanged();
         }
+        if (other.hasQueryId()) {
+          bitField0_ |= 0x00000020;
+          queryId_ = other.queryId_;
+          onChanged();
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -1734,6 +1825,80 @@ public final class CubeVisitProtos {
         return this;
       }
 
+      // optional string queryId = 6;
+      private java.lang.Object queryId_ = "";
+      /**
+       * <code>optional string queryId = 6;</code>
+       */
+      public boolean hasQueryId() {
+        return ((bitField0_ & 0x00000020) == 0x00000020);
+      }
+      /**
+       * <code>optional string queryId = 6;</code>
+       */
+      public java.lang.String getQueryId() {
+        java.lang.Object ref = queryId_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          queryId_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string queryId = 6;</code>
+       */
+      public com.google.protobuf.ByteString
+          getQueryIdBytes() {
+        java.lang.Object ref = queryId_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          queryId_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string queryId = 6;</code>
+       */
+      public Builder setQueryId(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000020;
+        queryId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string queryId = 6;</code>
+       */
+      public Builder clearQueryId() {
+        bitField0_ = (bitField0_ & ~0x00000020);
+        queryId_ = getDefaultInstance().getQueryId();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string queryId = 6;</code>
+       */
+      public Builder setQueryIdBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000020;
+        queryId_ = value;
+        onChanged();
+        return this;
+      }
+
       // @@protoc_insertion_point(builder_scope:CubeVisitRequest)
     }
 
@@ -4088,25 +4253,25 @@ public final class CubeVisitProtos {
     java.lang.String[] descriptorData = {
       "\npstorage-hbase/src/main/java/org/apache" +
       "/kylin/storage/hbase/cube/v2/coprocessor" +
-      "/endpoint/protobuf/CubeVisit.proto\"\302\001\n\020C" +
+      "/endpoint/protobuf/CubeVisit.proto\"\323\001\n\020C" +
       "ubeVisitRequest\022\025\n\rgtScanRequest\030\001 \002(\014\022\024" +
       "\n\014hbaseRawScan\030\002 \002(\014\022\032\n\022rowkeyPreambleSi" +
       "ze\030\003 \002(\005\0223\n\020hbaseColumnsToGT\030\004 \003(\0132\031.Cub" +
       "eVisitRequest.IntList\022\027\n\017kylinProperties" +
-      "\030\005 \002(\t\032\027\n\007IntList\022\014\n\004ints\030\001 \003(\005\"\321\002\n\021Cube" +
-      "VisitResponse\022\026\n\016compressedRows\030\001 \002(\014\022\'\n" +
-      "\005stats\030\002 \002(\0132\030.CubeVisitResponse.Stats\032\372",
-      "\001\n\005Stats\022\030\n\020serviceStartTime\030\001 \001(\003\022\026\n\016se" +
-      "rviceEndTime\030\002 \001(\003\022\027\n\017scannedRowCount\030\003 " +
-      "\001(\003\022\032\n\022aggregatedRowCount\030\004 \001(\003\022\025\n\rsyste" +
-      "mCpuLoad\030\005 \001(\001\022\036\n\026freePhysicalMemorySize" +
-      "\030\006 \001(\001\022\031\n\021freeSwapSpaceSize\030\007 \001(\001\022\020\n\010hos" +
-      "tname\030\010 \001(\t\022\016\n\006etcMsg\030\t \001(\t\022\026\n\016normalCom" +
-      "plete\030\n \001(\0052F\n\020CubeVisitService\0222\n\tvisit" +
-      "Cube\022\021.CubeVisitRequest\032\022.CubeVisitRespo" +
-      "nseB`\nEorg.apache.kylin.storage.hbase.cu" +
-      "be.v2.coprocessor.endpoint.generatedB\017Cu",
-      "beVisitProtosH\001\210\001\001\240\001\001"
+      "\030\005 \002(\t\022\017\n\007queryId\030\006 \001(\t\032\027\n\007IntList\022\014\n\004in" +
+      "ts\030\001 \003(\005\"\321\002\n\021CubeVisitResponse\022\026\n\016compre" +
+      "ssedRows\030\001 \002(\014\022\'\n\005stats\030\002 \002(\0132\030.CubeVisi",
+      "tResponse.Stats\032\372\001\n\005Stats\022\030\n\020serviceStar" +
+      "tTime\030\001 \001(\003\022\026\n\016serviceEndTime\030\002 \001(\003\022\027\n\017s" +
+      "cannedRowCount\030\003 \001(\003\022\032\n\022aggregatedRowCou" +
+      "nt\030\004 \001(\003\022\025\n\rsystemCpuLoad\030\005 \001(\001\022\036\n\026freeP" +
+      "hysicalMemorySize\030\006 \001(\001\022\031\n\021freeSwapSpace" +
+      "Size\030\007 \001(\001\022\020\n\010hostname\030\010 \001(\t\022\016\n\006etcMsg\030\t" +
+      " \001(\t\022\026\n\016normalComplete\030\n \001(\0052F\n\020CubeVisi" +
+      "tService\0222\n\tvisitCube\022\021.CubeVisitRequest" +
+      "\032\022.CubeVisitResponseB`\nEorg.apache.kylin" +
+      ".storage.hbase.cube.v2.coprocessor.endpo",
+      "int.generatedB\017CubeVisitProtosH\001\210\001\001\240\001\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -4118,7 +4283,7 @@ public final class CubeVisitProtos {
           internal_static_CubeVisitRequest_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_CubeVisitRequest_descriptor,
-              new java.lang.String[] { "GtScanRequest", "HbaseRawScan", "RowkeyPreambleSize", "HbaseColumnsToGT", "KylinProperties", });
+              new java.lang.String[] { "GtScanRequest", "HbaseRawScan", "RowkeyPreambleSize", "HbaseColumnsToGT", "KylinProperties", "QueryId", });
           internal_static_CubeVisitRequest_IntList_descriptor =
             internal_static_CubeVisitRequest_descriptor.getNestedTypes().get(0);
           internal_static_CubeVisitRequest_IntList_fieldAccessorTable = new

http://git-wip-us.apache.org/repos/asf/kylin/blob/db09f5f9/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/protobuf/CubeVisit.proto
----------------------------------------------------------------------
diff --git a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/protobuf/CubeVisit.proto b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/protobuf/CubeVisit.proto
index c84f4f3..1a56719 100644
--- a/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/protobuf/CubeVisit.proto
+++ b/storage-hbase/src/main/java/org/apache/kylin/storage/hbase/cube/v2/coprocessor/endpoint/protobuf/CubeVisit.proto
@@ -35,6 +35,7 @@ message CubeVisitRequest {
     required int32 rowkeyPreambleSize = 3;
     repeated IntList hbaseColumnsToGT = 4;
     required string kylinProperties = 5; // kylin properties
+    optional string queryId = 6;
     message IntList {
         repeated int32 ints = 1;
     }