You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2020/04/17 09:32:41 UTC

[skywalking] branch metrics updated: Adopt new sortMetrics query, make only topn query and H2/MySQL implementation into the new implementation.

This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch metrics
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/metrics by this push:
     new eb010f9  Adopt new sortMetrics query, make only topn query and H2/MySQL implementation into the new implementation.
eb010f9 is described below

commit eb010f9dbef6d886eeecf3185c4c110dd52b7174
Author: Wu Sheng <wu...@foxmail.com>
AuthorDate: Fri Apr 17 17:31:48 2020 +0800

    Adopt new sortMetrics query, make only topn query and H2/MySQL implementation into the new implementation.
---
 .../metrics/MetricsRegister.java}                  |  19 ++--
 .../server/core/query/AggregationQueryService.java | 104 ++++++------------
 .../oap/server/core/query/DurationUtils.java       |  22 ++--
 .../oap/server/core/query/input/Duration.java      |  17 ++-
 .../oap/server/core/query/input/Entity.java        |   6 ++
 .../oap/server/core/query/input/TopNCondition.java |  11 +-
 .../oap/server/core/query/type/TopNEntity.java     |  13 ++-
 .../core/storage/query/IAggregationQueryDAO.java   |  32 +++---
 .../query/graphql/resolver/AggregationQuery.java   | 116 +++++++++++++--------
 .../oap/query/graphql/resolver/MetricQuery.java    |  20 ++--
 .../oap/query/graphql/resolver/MetricsQuery.java   |  14 ++-
 .../oap/query/graphql/resolver/TopologyQuery.java  |  16 +--
 .../src/main/resources/query-protocol              |   2 +-
 .../plugin/jdbc/h2/dao/H2AggregationQueryDAO.java  |  96 ++++-------------
 .../jdbc/mysql/MySQLAggregationQueryDAO.java       |  51 ---------
 15 files changed, 234 insertions(+), 305 deletions(-)

diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNEntity.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/MetricsRegister.java
similarity index 77%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNEntity.java
copy to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/MetricsRegister.java
index d03bc2a..fd64fca 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNEntity.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/MetricsRegister.java
@@ -16,17 +16,12 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.type;
+package org.apache.skywalking.oap.server.core.analysis.metrics;
 
-import lombok.Getter;
-import lombok.Setter;
-
-
-@Deprecated
-@Getter
-@Setter
-public class TopNEntity {
-    private String name;
-    private String id;
-    private long value;
+/**
+ * MetricsRegister has the metadata of all metrics type
+ *
+ * @since 8.0.0
+ */
+public class MetricsRegister {
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AggregationQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AggregationQueryService.java
index 4b54402..57b9d79 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AggregationQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AggregationQueryService.java
@@ -19,11 +19,16 @@
 package org.apache.skywalking.oap.server.core.query;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
+import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
-import org.apache.skywalking.oap.server.core.query.enumeration.Order;
-import org.apache.skywalking.oap.server.core.query.type.TopNEntity;
+import org.apache.skywalking.oap.server.core.analysis.NodeType;
+import org.apache.skywalking.oap.server.core.analysis.manual.instance.InstanceTraffic;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
+import org.apache.skywalking.oap.server.core.query.type.KeyValue;
+import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
 import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
@@ -31,7 +36,6 @@ import org.apache.skywalking.oap.server.library.module.ModuleManager;
 import org.apache.skywalking.oap.server.library.module.Service;
 
 public class AggregationQueryService implements Service {
-
     private final ModuleManager moduleManager;
     private IAggregationQueryDAO aggregationQueryDAO;
 
@@ -48,75 +52,29 @@ public class AggregationQueryService implements Service {
         return aggregationQueryDAO;
     }
 
-    public List<TopNEntity> getServiceTopN(final String indName, final int topN, final DownSampling downsampling,
-                                           final long startTB, final long endTB, final Order order) throws IOException {
-        List<TopNEntity> topNEntities = getAggregationQueryDAO().getServiceTopN(
-            indName, ValueColumnMetadata.INSTANCE.getValueCName(indName), topN, downsampling, startTB, endTB, order);
-        for (TopNEntity entity : topNEntities) {
-            entity.setName(IDManager.ServiceID.analysisId(entity.getId()).getName());
-        }
-        return topNEntities;
-    }
-
-    public List<TopNEntity> getAllServiceInstanceTopN(final String indName,
-                                                      final int topN,
-                                                      final DownSampling downsampling,
-                                                      final long startTB,
-                                                      final long endTB,
-                                                      final Order order) throws IOException {
-        List<TopNEntity> topNEntities = getAggregationQueryDAO().getAllServiceInstanceTopN(
-            indName, ValueColumnMetadata.INSTANCE
-                .getValueCName(indName), topN, downsampling, startTB, endTB, order);
-        for (TopNEntity entity : topNEntities) {
-            entity.setName(IDManager.ServiceInstanceID.analysisId(entity.getId()).getName());
-        }
-        return topNEntities;
-    }
-
-    public List<TopNEntity> getServiceInstanceTopN(final String serviceId,
-                                                   final String indName,
-                                                   final int topN,
-                                                   final DownSampling downsampling,
-                                                   final long startTB,
-                                                   final long endTB,
-                                                   final Order order) throws IOException {
-        List<TopNEntity> topNEntities = getAggregationQueryDAO().getServiceInstanceTopN(
-            serviceId, indName, ValueColumnMetadata.INSTANCE
-                .getValueCName(indName), topN, downsampling, startTB, endTB, order);
-        for (TopNEntity entity : topNEntities) {
-            entity.setName(IDManager.ServiceInstanceID.analysisId(entity.getId()).getName());
-        }
-        return topNEntities;
-    }
-
-    public List<TopNEntity> getAllEndpointTopN(final String indName,
-                                               final int topN,
-                                               final DownSampling downsampling,
-                                               final long startTB,
-                                               final long endTB,
-                                               final Order order) throws IOException {
-        List<TopNEntity> topNEntities = getAggregationQueryDAO().getAllEndpointTopN(
-            indName, ValueColumnMetadata.INSTANCE.getValueCName(indName), topN, downsampling, startTB, endTB, order);
-
-        for (TopNEntity entity : topNEntities) {
-            entity.setName(IDManager.EndpointID.analysisId(entity.getId()).getEndpointName());
-        }
-        return topNEntities;
-    }
-
-    public List<TopNEntity> getEndpointTopN(final String serviceId,
-                                            final String indName,
-                                            final int topN,
-                                            final DownSampling downsampling,
-                                            final long startTB,
-                                            final long endTB,
-                                            final Order order) throws IOException {
-        List<TopNEntity> topNEntities = getAggregationQueryDAO().getEndpointTopN(
-            serviceId, indName, ValueColumnMetadata.INSTANCE
-                .getValueCName(indName), topN, downsampling, startTB, endTB, order);
-        for (TopNEntity entity : topNEntities) {
-            entity.setName(IDManager.EndpointID.analysisId(entity.getId()).getEndpointName());
+    public List<SelectedRecord> sortMetrics(TopNCondition metrics, Duration duration) throws IOException {
+        final String valueCName = ValueColumnMetadata.INSTANCE.getValueCName(metrics.getName());
+        List<KeyValue> additionalConditions = null;
+        if (StringUtil.isNotEmpty(metrics.getParentService())) {
+            additionalConditions = new ArrayList<>(1);
+            final String serviceId = IDManager.ServiceID.buildId(metrics.getParentService(), NodeType.Normal);
+            additionalConditions.add(new KeyValue(InstanceTraffic.SERVICE_ID, serviceId));
         }
-        return topNEntities;
+        final List<SelectedRecord> selectedRecords = getAggregationQueryDAO().sortMetrics(
+            metrics, valueCName, duration, additionalConditions);
+        selectedRecords.forEach(selectedRecord -> {
+            switch (metrics.getScope()) {
+                case Service:
+                    selectedRecord.setName(IDManager.ServiceID.analysisId(selectedRecord.getId()).getName());
+                    break;
+                case ServiceInstance:
+                    selectedRecord.setName(IDManager.ServiceInstanceID.analysisId(selectedRecord.getId()).getName());
+                    break;
+                case Endpoint:
+                    selectedRecord.setName(IDManager.ServiceInstanceID.analysisId(selectedRecord.getId()).getName());
+                    break;
+            }
+        });
+        return selectedRecords;
     }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java
index 3d3d9ca..76ba1bb 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java
@@ -41,7 +41,11 @@ public enum DurationUtils {
     private static final DateTimeFormatter YYYYMMDDHHMM = DateTimeFormat.forPattern("yyyyMMddHHmm");
     private static final DateTimeFormatter YYYYMMDDHHMMSS = DateTimeFormat.forPattern("yyyyMMddHHmmss");
 
-    public long exchangeToTimeBucket(String dateStr) {
+    /**
+     * Convert date in `yyyy-MM-dd HHmmss` style to `yyyyMMddHHmmss` no matter the precision. Such as, in day precision,
+     * this covert `yyyy-MM-dd` style to `yyyyMMdd`.
+     */
+    public long convertToTimeBucket(String dateStr) {
         dateStr = dateStr.replaceAll(Const.LINE, Const.EMPTY_STRING);
         dateStr = dateStr.replaceAll(Const.SPACE, Const.EMPTY_STRING);
         return Long.parseLong(dateStr);
@@ -51,16 +55,16 @@ public enum DurationUtils {
         long secondTimeBucket = 0;
         switch (step) {
             case DAY:
-                secondTimeBucket = exchangeToTimeBucket(dateStr) * 100 * 100 * 100;
+                secondTimeBucket = convertToTimeBucket(dateStr) * 100 * 100 * 100;
                 break;
             case HOUR:
-                secondTimeBucket = exchangeToTimeBucket(dateStr) * 100 * 100;
+                secondTimeBucket = convertToTimeBucket(dateStr) * 100 * 100;
                 break;
             case MINUTE:
-                secondTimeBucket = exchangeToTimeBucket(dateStr) * 100;
+                secondTimeBucket = convertToTimeBucket(dateStr) * 100;
                 break;
             case SECOND:
-                secondTimeBucket = exchangeToTimeBucket(dateStr);
+                secondTimeBucket = convertToTimeBucket(dateStr);
                 break;
         }
         return secondTimeBucket;
@@ -70,16 +74,16 @@ public enum DurationUtils {
         long secondTimeBucket = 0;
         switch (step) {
             case DAY:
-                secondTimeBucket = ((exchangeToTimeBucket(dateStr) * 100 + 99) * 100 + 99) * 100 + 99;
+                secondTimeBucket = ((convertToTimeBucket(dateStr) * 100 + 99) * 100 + 99) * 100 + 99;
                 break;
             case HOUR:
-                secondTimeBucket = (exchangeToTimeBucket(dateStr) * 100 + 99) * 100 + 99;
+                secondTimeBucket = (convertToTimeBucket(dateStr) * 100 + 99) * 100 + 99;
                 break;
             case MINUTE:
-                secondTimeBucket = exchangeToTimeBucket(dateStr) * 100 + 99;
+                secondTimeBucket = convertToTimeBucket(dateStr) * 100 + 99;
                 break;
             case SECOND:
-                secondTimeBucket = exchangeToTimeBucket(dateStr);
+                secondTimeBucket = convertToTimeBucket(dateStr);
                 break;
         }
         return secondTimeBucket;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java
index ef0147d..7605ce0 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java
@@ -18,12 +18,25 @@
 
 package org.apache.skywalking.oap.server.core.query.input;
 
-import lombok.Getter;
+import org.apache.skywalking.oap.server.core.query.DurationUtils;
 import org.apache.skywalking.oap.server.core.query.enumeration.Step;
 
-@Getter
 public class Duration {
     private String start;
     private String end;
     private Step step;
+
+    /**
+     * See {@link DurationUtils#convertToTimeBucket(String)}
+     */
+    public long getStartTimeBucket() {
+        return DurationUtils.INSTANCE.convertToTimeBucket(start);
+    }
+
+    /**
+     * See {@link DurationUtils#convertToTimeBucket(String)}
+     */
+    public long getEndTimeBucket() {
+        return DurationUtils.INSTANCE.convertToTimeBucket(end);
+    }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Entity.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Entity.java
index d61654c..644c4e3 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Entity.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Entity.java
@@ -59,4 +59,10 @@ public class Entity {
     private boolean destIsNormal;
     private String destServiceInstanceName;
     private String destEndpointName;
+
+    public boolean isService(){
+        return Scope.Service.equals(scope);
+    }
+
+
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TopNCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TopNCondition.java
index efa1e8f..a55c7bd 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TopNCondition.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TopNCondition.java
@@ -19,13 +19,16 @@
 package org.apache.skywalking.oap.server.core.query.input;
 
 import lombok.Getter;
+import lombok.Setter;
 import org.apache.skywalking.oap.server.core.query.enumeration.Order;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
 
 /**
  * Top N query condition.
  *
  * @since 8.0.0
  */
+@Setter
 @Getter
 public class TopNCondition {
     /**
@@ -35,7 +38,13 @@ public class TopNCondition {
     /**
      * See {@link Entity}
      */
-    private Entity parentEntity;
+    private String parentService;
+    /**
+     * Indicate the metrics entity scope. Because this is a top list, don't need to set the Entity like the
+     * MetricsCondition. Only accept scope = {@link Scope#Service} {@link Scope#ServiceInstance} and {@link
+     * Scope#Endpoint}, ignore others due to those are pointless.
+     */
+    private Scope scope;
     private int topN;
     private Order order;
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNEntity.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNEntity.java
index d03bc2a..697c570 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNEntity.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNEntity.java
@@ -21,7 +21,9 @@ package org.apache.skywalking.oap.server.core.query.type;
 import lombok.Getter;
 import lombok.Setter;
 
-
+/**
+ * @since 8.0.0 replaced by {@link SelectedRecord}
+ */
 @Deprecated
 @Getter
 @Setter
@@ -29,4 +31,13 @@ public class TopNEntity {
     private String name;
     private String id;
     private long value;
+
+    public TopNEntity() {
+    }
+
+    public TopNEntity(SelectedRecord record) {
+        this.name = record.getName();
+        this.id = record.getId();
+        this.value = Long.parseLong(record.getValue());
+    }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IAggregationQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IAggregationQueryDAO.java
index f38e53a..e520d3c 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IAggregationQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IAggregationQueryDAO.java
@@ -20,26 +20,20 @@ package org.apache.skywalking.oap.server.core.storage.query;
 
 import java.io.IOException;
 import java.util.List;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
-import org.apache.skywalking.oap.server.core.query.enumeration.Order;
-import org.apache.skywalking.oap.server.core.query.type.TopNEntity;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
+import org.apache.skywalking.oap.server.core.query.type.KeyValue;
+import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
 import org.apache.skywalking.oap.server.core.storage.DAO;
 
+/**
+ * Query ordered list, based on storage side aggregation. Most storage supports `groupby`/`aggregation` query.
+ *
+ * @since 8.0.0
+ */
 public interface IAggregationQueryDAO extends DAO {
-
-    List<TopNEntity> getServiceTopN(final String indName, String valueCName, final int topN,
-                                    final DownSampling downsampling, final long startTB, final long endTB, final Order order) throws IOException;
-
-    List<TopNEntity> getAllServiceInstanceTopN(final String indName, String valueCName, final int topN,
-                                               final DownSampling downsampling, final long startTB, final long endTB, final Order order) throws IOException;
-
-    List<TopNEntity> getServiceInstanceTopN(final String serviceId, final String indName, String valueCName,
-                                            final int topN, final DownSampling downsampling, final long startTB, final long endTB,
-                                            final Order order) throws IOException;
-
-    List<TopNEntity> getAllEndpointTopN(final String indName, String valueCName, final int topN,
-                                        final DownSampling downsampling, final long startTB, final long endTB, final Order order) throws IOException;
-
-    List<TopNEntity> getEndpointTopN(final String serviceId, final String indName, String valueCName, final int topN,
-                                     final DownSampling downsampling, final long startTB, final long endTB, final Order order) throws IOException;
+    List<SelectedRecord> sortMetrics(TopNCondition metrics,
+                                     String valueColumnName,
+                                     Duration duration,
+                                     List<KeyValue> additionalConditions) throws IOException;
 }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AggregationQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AggregationQuery.java
index 24b2588..d889d3a 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AggregationQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AggregationQuery.java
@@ -20,75 +20,103 @@ package org.apache.skywalking.oap.query.graphql.resolver;
 
 import com.coxautodev.graphql.tools.GraphQLQueryResolver;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
-import org.apache.skywalking.oap.server.core.query.input.Duration;
-import org.apache.skywalking.oap.server.core.CoreModule;
-import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
-import org.apache.skywalking.oap.server.core.query.DurationUtils;
-import org.apache.skywalking.oap.server.core.query.StepToDownSampling;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.query.enumeration.Order;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
 import org.apache.skywalking.oap.server.core.query.type.TopNEntity;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
 /**
- * @since 8.0.0 This query is replaced by {@link MetricsQuery}
+ * @since 8.0.0 This query is replaced by {@link MetricsQuery}, all queries have been delegated to there.
  */
 @Deprecated
 public class AggregationQuery implements GraphQLQueryResolver {
-
-    private final ModuleManager moduleManager;
-    private AggregationQueryService queryService;
+    private MetricsQuery query;
 
     public AggregationQuery(ModuleManager moduleManager) {
-        this.moduleManager = moduleManager;
-    }
-
-    private AggregationQueryService getQueryService() {
-        if (queryService == null) {
-            this.queryService = moduleManager.find(CoreModule.NAME)
-                                             .provider()
-                                             .getService(AggregationQueryService.class);
-        }
-        return queryService;
+        query = new MetricsQuery(moduleManager);
     }
 
     public List<TopNEntity> getServiceTopN(final String name, final int topN, final Duration duration,
-        final Order order) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
-
-        return getQueryService().getServiceTopN(name, topN, StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket, order);
+                                           final Order order) throws IOException {
+        TopNCondition condition = new TopNCondition();
+        condition.setName(name);
+        condition.setScope(Scope.Service);
+        condition.setOrder(order);
+        condition.setTopN(topN);
+        List<TopNEntity> list = new ArrayList<>();
+        query.sortMetrics(condition, duration).forEach(selectedRecord -> {
+            TopNEntity entity = new TopNEntity(selectedRecord);
+            list.add(entity);
+        });
+        return list;
     }
 
     public List<TopNEntity> getAllServiceInstanceTopN(final String name, final int topN, final Duration duration,
-        final Order order) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
-
-        return getQueryService().getAllServiceInstanceTopN(name, topN, StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket, order);
+                                                      final Order order) throws IOException {
+        TopNCondition condition = new TopNCondition();
+        condition.setName(name);
+        condition.setScope(Scope.ServiceInstance);
+        condition.setOrder(order);
+        condition.setTopN(topN);
+        List<TopNEntity> list = new ArrayList<>();
+        query.sortMetrics(condition, duration).forEach(selectedRecord -> {
+            TopNEntity entity = new TopNEntity(selectedRecord);
+            list.add(entity);
+        });
+        return list;
     }
 
     public List<TopNEntity> getServiceInstanceTopN(final String serviceId, final String name, final int topN,
-        final Duration duration, final Order order) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
-
-        return getQueryService().getServiceInstanceTopN(serviceId, name, topN, StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket, order);
+                                                   final Duration duration, final Order order) throws IOException {
+        TopNCondition condition = new TopNCondition();
+        condition.setName(name);
+        condition.setScope(Scope.ServiceInstance);
+        final IDManager.ServiceID.ServiceIDDefinition serviceIDDefinition = IDManager.ServiceID.analysisId(serviceId);
+        condition.setParentService(serviceIDDefinition.getName());
+        condition.setOrder(order);
+        condition.setTopN(topN);
+        List<TopNEntity> list = new ArrayList<>();
+        query.sortMetrics(condition, duration).forEach(selectedRecord -> {
+            TopNEntity entity = new TopNEntity(selectedRecord);
+            list.add(entity);
+        });
+        return list;
     }
 
     public List<TopNEntity> getAllEndpointTopN(final String name, final int topN, final Duration duration,
-        final Order order) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
-
-        return getQueryService().getAllEndpointTopN(name, topN, StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket, order);
+                                               final Order order) throws IOException {
+        TopNCondition condition = new TopNCondition();
+        condition.setName(name);
+        condition.setScope(Scope.Endpoint);
+        condition.setOrder(order);
+        condition.setTopN(topN);
+        List<TopNEntity> list = new ArrayList<>();
+        query.sortMetrics(condition, duration).forEach(selectedRecord -> {
+            TopNEntity entity = new TopNEntity(selectedRecord);
+            list.add(entity);
+        });
+        return list;
     }
 
     public List<TopNEntity> getEndpointTopN(final String serviceId, final String name, final int topN,
-        final Duration duration, final Order order) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
-
-        return getQueryService().getEndpointTopN(serviceId, name, topN, StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket, order);
+                                            final Duration duration, final Order order) throws IOException {
+        TopNCondition condition = new TopNCondition();
+        condition.setName(name);
+        condition.setScope(Scope.Endpoint);
+        final IDManager.ServiceID.ServiceIDDefinition serviceIDDefinition = IDManager.ServiceID.analysisId(serviceId);
+        condition.setParentService(serviceIDDefinition.getName());
+        condition.setOrder(order);
+        condition.setTopN(topN);
+        List<TopNEntity> list = new ArrayList<>();
+        query.sortMetrics(condition, duration).forEach(selectedRecord -> {
+            TopNEntity entity = new TopNEntity(selectedRecord);
+            list.add(entity);
+        });
+        return list;
     }
 }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricQuery.java
index 53a5297..3f33f33 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricQuery.java
@@ -56,8 +56,8 @@ public class MetricQuery implements GraphQLQueryResolver {
     }
 
     public IntValues getValues(final BatchMetricConditions metrics, final Duration duration) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
+        long startTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getStart());
+        long endTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getEnd());
 
         return getMetricQueryService().getValues(metrics.getName(), metrics.getIds(), StepToDownSampling.transform(duration
             .getStep()), startTimeBucket, endTimeBucket);
@@ -65,8 +65,8 @@ public class MetricQuery implements GraphQLQueryResolver {
 
     public IntValues getLinearIntValues(final MetricCondition metrics,
         final Duration duration) throws IOException, ParseException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
+        long startTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getStart());
+        long endTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getEnd());
 
         return getMetricQueryService().getLinearIntValues(metrics.getName(), metrics.getId(), StepToDownSampling.transform(duration
             .getStep()), startTimeBucket, endTimeBucket);
@@ -74,8 +74,8 @@ public class MetricQuery implements GraphQLQueryResolver {
 
     public List<IntValues> getMultipleLinearIntValues(final MetricCondition metrics, final int numOfLinear,
         final Duration duration) throws IOException, ParseException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
+        long startTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getStart());
+        long endTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getEnd());
 
         return getMetricQueryService().getMultipleLinearIntValues(metrics.getName(), metrics.getId(), numOfLinear, StepToDownSampling
             .transform(duration.getStep()), startTimeBucket, endTimeBucket);
@@ -83,8 +83,8 @@ public class MetricQuery implements GraphQLQueryResolver {
 
     public List<IntValues> getSubsetOfMultipleLinearIntValues(final MetricCondition metrics,
         final List<Integer> linearIndex, final Duration duration) throws IOException, ParseException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
+        long startTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getStart());
+        long endTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getEnd());
 
         return getMetricQueryService().getSubsetOfMultipleLinearIntValues(metrics.getName(), metrics.getId(), linearIndex, StepToDownSampling
             .transform(duration.getStep()), startTimeBucket, endTimeBucket);
@@ -92,8 +92,8 @@ public class MetricQuery implements GraphQLQueryResolver {
 
     public Thermodynamic getThermodynamic(final MetricCondition metrics,
         final Duration duration) throws IOException, ParseException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
+        long startTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getStart());
+        long endTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getEnd());
 
         return getMetricQueryService().getThermodynamic(metrics.getName(), metrics.getId(), StepToDownSampling.transform(duration
             .getStep()), startTimeBucket, endTimeBucket);
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsQuery.java
index a1e2a0c..59f26a4 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsQuery.java
@@ -22,6 +22,8 @@ import com.coxautodev.graphql.tools.GraphQLQueryResolver;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
+import org.apache.skywalking.oap.server.core.CoreModule;
+import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
 import org.apache.skywalking.oap.server.core.query.MetricQueryService;
 import org.apache.skywalking.oap.server.core.query.enumeration.MetricsType;
 import org.apache.skywalking.oap.server.core.query.input.Duration;
@@ -40,11 +42,21 @@ import org.apache.skywalking.oap.server.library.module.ModuleManager;
 public class MetricsQuery implements GraphQLQueryResolver {
     private final ModuleManager moduleManager;
     private MetricQueryService metricQueryService;
+    private AggregationQueryService queryService;
 
     public MetricsQuery(ModuleManager moduleManager) {
         this.moduleManager = moduleManager;
     }
 
+    private AggregationQueryService getQueryService() {
+        if (queryService == null) {
+            this.queryService = moduleManager.find(CoreModule.NAME)
+                                             .provider()
+                                             .getService(AggregationQueryService.class);
+        }
+        return queryService;
+    }
+
     /**
      * Metrics definition metadata query. Response the metrics type which determines the suitable query methods.
      *
@@ -78,7 +90,7 @@ public class MetricsQuery implements GraphQLQueryResolver {
      * @since 8.0.0
      */
     public List<SelectedRecord> sortMetrics(TopNCondition metrics, Duration duration) throws IOException {
-        return Collections.emptyList();
+        return getQueryService().sortMetrics(metrics, duration);
     }
 
     /**
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopologyQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopologyQuery.java
index 7eab41f..00b669e 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopologyQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopologyQuery.java
@@ -48,8 +48,8 @@ public class TopologyQuery implements GraphQLQueryResolver {
     }
 
     public Topology getGlobalTopology(final Duration duration) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
+        long startTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getStart());
+        long endTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getEnd());
 
         return getQueryService().getGlobalTopology(
             StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket);
@@ -62,8 +62,8 @@ public class TopologyQuery implements GraphQLQueryResolver {
     }
 
     public Topology getServicesTopology(final List<String> serviceIds, final Duration duration) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
+        long startTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getStart());
+        long endTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getEnd());
 
         return getQueryService().getServiceTopology(
             StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket, serviceIds);
@@ -71,8 +71,8 @@ public class TopologyQuery implements GraphQLQueryResolver {
 
     public ServiceInstanceTopology getServiceInstanceTopology(final String clientServiceId, final String serverServiceId,
                                                               final Duration duration) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
+        long startTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getStart());
+        long endTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getEnd());
 
         return getQueryService().getServiceInstanceTopology(
             clientServiceId, serverServiceId, StepToDownSampling.transform(duration
@@ -82,8 +82,8 @@ public class TopologyQuery implements GraphQLQueryResolver {
     }
 
     public Topology getEndpointTopology(final String endpointId, final Duration duration) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
+        long startTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getStart());
+        long endTimeBucket = DurationUtils.INSTANCE.convertToTimeBucket(duration.getEnd());
 
         return getQueryService().getEndpointTopology(
             StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket, endpointId);
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
index b60f4fb..236cfa5 160000
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
@@ -1 +1 @@
-Subproject commit b60f4fbcd8ad79157222cad7879d96ffffbf17fe
+Subproject commit 236cfa50da15768327fe39581249fd4ff519364f
diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AggregationQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AggregationQueryDAO.java
index 3200e6f..2f6ec06 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AggregationQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AggregationQueryDAO.java
@@ -31,6 +31,10 @@ import org.apache.skywalking.oap.server.core.analysis.manual.endpoint.EndpointTr
 import org.apache.skywalking.oap.server.core.analysis.manual.instance.InstanceTraffic;
 import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
 import org.apache.skywalking.oap.server.core.query.enumeration.Order;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
+import org.apache.skywalking.oap.server.core.query.type.KeyValue;
+import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
 import org.apache.skywalking.oap.server.core.query.type.TopNEntity;
 import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
@@ -45,89 +49,39 @@ public class H2AggregationQueryDAO implements IAggregationQueryDAO {
     }
 
     @Override
-    public List<TopNEntity> getServiceTopN(String indName, String valueCName, int topN, DownSampling downsampling,
-                                           long startTB, long endTB, Order order) throws IOException {
-        return topNQuery(indName, valueCName, topN, downsampling, startTB, endTB, order, null);
-    }
-
-    @Override
-    public List<TopNEntity> getAllServiceInstanceTopN(String indName,
-                                                      String valueCName,
-                                                      int topN,
-                                                      DownSampling downsampling,
-                                                      long startTB,
-                                                      long endTB,
-                                                      Order order) throws IOException {
-        return topNQuery(indName, valueCName, topN, downsampling, startTB, endTB, order, null);
-    }
-
-    @Override
-    public List<TopNEntity> getServiceInstanceTopN(String serviceId,
-                                                   String indName,
-                                                   String valueCName,
-                                                   int topN,
-                                                   DownSampling downsampling,
-                                                   long startTB,
-                                                   long endTB,
-                                                   Order order) throws IOException {
-        return topNQuery(indName, valueCName, topN, downsampling, startTB, endTB, order, (sql, conditions) -> {
-            sql.append(" and ").append(InstanceTraffic.SERVICE_ID).append("=?");
-            conditions.add(serviceId);
-        });
-    }
-
-    @Override
-    public List<TopNEntity> getAllEndpointTopN(String indName, String valueCName, int topN, DownSampling downsampling,
-                                               long startTB, long endTB, Order order) throws IOException {
-        return topNQuery(indName, valueCName, topN, downsampling, startTB, endTB, order, null);
-    }
-
-    @Override
-    public List<TopNEntity> getEndpointTopN(String serviceId,
-                                            String indName,
-                                            String valueCName,
-                                            int topN,
-                                            DownSampling downsampling,
-                                            long startTB,
-                                            long endTB,
-                                            Order order) throws IOException {
-        return topNQuery(indName, valueCName, topN, downsampling, startTB, endTB, order, (sql, conditions) -> {
-            sql.append(" and ").append(EndpointTraffic.SERVICE_ID).append("=?");
-            conditions.add(serviceId);
-        });
-    }
-
-    public List<TopNEntity> topNQuery(String indexName,
-                                      String valueCName,
-                                      int topN,
-                                      DownSampling downsampling,
-                                      long startTB,
-                                      long endTB,
-                                      Order order,
-                                      AppendCondition appender) throws IOException {
+    public List<SelectedRecord> sortMetrics(final TopNCondition metrics,
+                                            final String valueColumnName,
+                                            final Duration duration,
+                                            List<KeyValue> additionalConditions) throws IOException {
         StringBuilder sql = new StringBuilder();
         List<Object> conditions = new ArrayList<>(10);
         sql.append("select * from (select avg(")
-           .append(valueCName)
+           .append(valueColumnName)
            .append(") value,")
            .append(Metrics.ENTITY_ID)
            .append(" from ")
-           .append(indexName)
+           .append(metrics.getName())
            .append(" where ");
-        this.setTimeRangeCondition(sql, conditions, startTB, endTB);
-        if (appender != null) {
-            appender.append(sql, conditions);
+        this.setTimeRangeCondition(sql, conditions, duration.getStartTimeBucket(), duration.getEndTimeBucket());
+        if (additionalConditions != null) {
+            additionalConditions.forEach(condition -> {
+                sql.append(" and ").append(condition.getKey()).append("=?");
+                conditions.add(condition.getValue());
+            });
         }
         sql.append(" group by ").append(Metrics.ENTITY_ID);
-        sql.append(") order by value ").append(order.equals(Order.ASC) ? "asc" : "desc").append(" limit ").append(topN);
-        List<TopNEntity> topNEntities = new ArrayList<>();
+        sql.append(") order by value ")
+           .append(metrics.getOrder().equals(Order.ASC) ? "asc" : "desc")
+           .append(" limit ")
+           .append(metrics.getTopN());
+        List<SelectedRecord> topNEntities = new ArrayList<>();
         try (Connection connection = h2Client.getConnection();
              ResultSet resultSet = h2Client.executeQuery(
                  connection, sql.toString(), conditions.toArray(new Object[0]))) {
             while (resultSet.next()) {
-                TopNEntity topNEntity = new TopNEntity();
+                SelectedRecord topNEntity = new SelectedRecord();
                 topNEntity.setId(resultSet.getString(Metrics.ENTITY_ID));
-                topNEntity.setValue(resultSet.getLong("value"));
+                topNEntity.setValue(resultSet.getString("value"));
                 topNEntities.add(topNEntity);
             }
         } catch (SQLException e) {
@@ -142,8 +96,4 @@ public class H2AggregationQueryDAO implements IAggregationQueryDAO {
         conditions.add(startTimestamp);
         conditions.add(endTimestamp);
     }
-
-    protected interface AppendCondition {
-        void append(StringBuilder sql, List<Object> conditions);
-    }
 }
diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLAggregationQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLAggregationQueryDAO.java
index 3f6dddc..34339b0 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLAggregationQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLAggregationQueryDAO.java
@@ -18,16 +18,6 @@
 
 package org.apache.skywalking.oap.server.storage.plugin.jdbc.mysql;
 
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
-import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
-import org.apache.skywalking.oap.server.core.query.enumeration.Order;
-import org.apache.skywalking.oap.server.core.query.type.TopNEntity;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2AggregationQueryDAO;
 
@@ -36,45 +26,4 @@ public class MySQLAggregationQueryDAO extends H2AggregationQueryDAO {
     public MySQLAggregationQueryDAO(JDBCHikariCPClient client) {
         super(client);
     }
-
-    @Override
-    public List<TopNEntity> topNQuery(String tableName,
-                                      String valueCName,
-                                      int topN,
-                                      DownSampling downsampling,
-                                      long startTB,
-                                      long endTB,
-                                      Order order,
-                                      AppendCondition appender) throws IOException {
-        StringBuilder sql = new StringBuilder();
-        List<Object> conditions = new ArrayList<>(10);
-        sql.append("select avg(")
-           .append(valueCName)
-           .append(") value,")
-           .append(Metrics.ENTITY_ID)
-           .append(" from ")
-           .append(tableName)
-           .append(" where ");
-        this.setTimeRangeCondition(sql, conditions, startTB, endTB);
-        if (appender != null) {
-            appender.append(sql, conditions);
-        }
-        sql.append(" group by ").append(Metrics.ENTITY_ID);
-        sql.append(" order by value ").append(order.equals(Order.ASC) ? "asc" : "desc").append(" limit ").append(topN);
-
-        List<TopNEntity> topNEntities = new ArrayList<>();
-        try (Connection connection = getH2Client().getConnection();
-             ResultSet resultSet = getH2Client().executeQuery(
-                 connection, sql.toString(), conditions.toArray(new Object[0]))) {
-            while (resultSet.next()) {
-                TopNEntity topNEntity = new TopNEntity();
-                topNEntity.setId(resultSet.getString(Metrics.ENTITY_ID));
-                topNEntity.setValue(resultSet.getLong("value"));
-                topNEntities.add(topNEntity);
-            }
-        } catch (SQLException e) {
-            throw new IOException(e);
-        }
-        return topNEntities;
-    }
 }