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/21 07:39:30 UTC

[skywalking] branch master updated: New metrics query protocol v2 (#4679)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 418bdff  New metrics query protocol v2 (#4679)
418bdff is described below

commit 418bdff277179b4660e578b1837f21fd3db514cb
Author: 吴晟 Wu Sheng <wu...@foxmail.com>
AuthorDate: Tue Apr 21 15:39:18 2020 +0800

    New metrics query protocol v2 (#4679)
    
    1. Support the new query protocol, and the v1 query protocol is still supported
    2. All `numOfxxx`/`GlobalBrief` is only a mock now, no real number.
    3. typeOfMetrics service is a mock only too, follow up PR will implement this.
---
 .../skywalking/oal/rt/parser/AnalysisResult.java   |   4 +-
 .../oal/rt/parser/PersistenceColumns.java          |  10 +-
 .../code-templates/metrics/deserialize.ftl         |  10 +-
 .../resources/code-templates/metrics/serialize.ftl |  12 +-
 .../alarm/provider/grpc/GRPChookCallbackTest.java  |   2 +-
 .../src/main/resources/official_analysis.oal       |   2 +-
 .../skywalking/oap/server/core/CoreModule.java     |   4 +-
 .../oap/server/core/CoreModuleProvider.java        |   4 +-
 .../oap/server/core/analysis/IDManager.java        |  11 +-
 .../oap/server/core/analysis/TimeBucket.java       |   8 -
 .../analysis/manual/log/AbstractLogRecord.java     |   2 +-
 .../server/core/analysis/metrics/DataTable.java    | 119 ++++++++++
 .../server/core/analysis/metrics/GroupMetrics.java |  32 ---
 ...modynamicMetrics.java => HistogramMetrics.java} |  60 +++--
 .../core/analysis/metrics/IntKeyLongValue.java     |  96 --------
 .../analysis/metrics/IntKeyLongValueHashMap.java   |  77 ------
 .../metrics/MetricsRegister.java}                  |  10 +-
 .../core/analysis/metrics/PercentileMetrics.java   |  62 ++---
 .../server/core/analysis/metrics/PxxMetrics.java   |  38 ++-
 .../oap/server/core/cache/CacheUpdateTimer.java    |   2 +-
 .../oap/server/core/cache/ProfileTaskCache.java    |   2 +-
 .../oap/server/core/command/CommandService.java    |   2 +-
 .../core/profile/ProfileTaskMutationService.java   |   4 +-
 .../profile/analyze/ProfileAnalyzeCollector.java   |   2 +-
 .../core/profile/analyze/ProfileAnalyzer.java      |   6 +-
 .../core/profile/analyze/ProfileStackNode.java     |   4 +-
 .../server/core/query/AggregationQueryService.java | 106 +++------
 .../oap/server/core/query/AlarmQueryService.java   |   4 +-
 .../oap/server/core/query/DurationUtils.java       | 155 +++++-------
 .../oap/server/core/query/LogQueryService.java     |   6 +-
 .../server/core/query/MetadataQueryService.java    |  22 +-
 .../oap/server/core/query/MetricQueryService.java  | 138 -----------
 .../oap/server/core/query/MetricsQueryService.java |  85 +++++++
 .../oap/server/core/query/PaginationUtils.java     |   2 +-
 .../query/{DurationPoint.java => PointOfTime.java} |  37 +--
 .../server/core/query/ProfileTaskQueryService.java |  18 +-
 .../core/query/ServiceInstanceTopologyBuilder.java |   6 +-
 .../server/core/query/ServiceTopologyBuilder.java  |   6 +-
 .../oap/server/core/query/StepToDownSampling.java  |  39 ---
 .../server/core/query/TopNRecordsQueryService.java |  10 +-
 .../server/core/query/TopologyQueryService.java    |  38 ++-
 .../oap/server/core/query/TraceQueryService.java   |  20 +-
 .../server/core/query/entity/Thermodynamic.java    |  63 -----
 .../Language.java}                                 |   8 +-
 .../enumeration/MetricsType.java}                  |  30 +--
 .../core/query/{entity => enumeration}/Order.java  |   2 +-
 .../core/query/{entity => enumeration}/Scope.java  |  10 +-
 .../core/query/{entity => enumeration}/Step.java   |   2 +-
 .../oap/server/core/query/input/Duration.java      |  69 ++++++
 .../oap/server/core/query/input/Entity.java        | 112 +++++++++
 .../core/query/input}/LogQueryCondition.java       |   6 +-
 .../server/core/query/input}/MetricCondition.java  |   2 +-
 .../Database.java => input/MetricsCondition.java}  |  17 +-
 .../query/input}/ProfileTaskCreationRequest.java   |   4 +-
 .../oap/server/core/query/input/TopNCondition.java |  55 +++++
 .../core/query/input}/TraceQueryCondition.java     |   8 +-
 .../core/query/{entity => type}/AlarmMessage.java  |   3 +-
 .../core/query/{entity => type}/AlarmTrend.java    |   2 +-
 .../server/core/query/{entity => type}/Alarms.java |   2 +-
 .../core/query/{entity => type}/Attribute.java     |   2 +-
 .../core/query/{entity => type}/BasicTrace.java    |   2 +-
 .../oap/server/core/query/type/Bucket.java         |  82 +++++++
 .../server/core/query/{entity => type}/Call.java   |   2 +-
 .../core/query/{entity => type}/ClusterBrief.java  |  13 +-
 .../core/query/{entity => type}/ContentType.java   |   2 +-
 .../core/query/{entity => type}/Database.java      |   2 +-
 .../core/query/{entity => type}/Endpoint.java      |   2 +-
 .../core/query/{entity => type}/EndpointInfo.java  |   2 +-
 .../oap/server/core/query/type/HeatMap.java        | 113 +++++++++
 .../core/query/{entity => type}/IntValues.java     |  21 +-
 .../server/core/query/{entity => type}/KVInt.java  |   2 +-
 .../core/query/{entity => type}/KeyValue.java      |   2 +-
 .../server/core/query/{entity => type}/Log.java    |   2 +-
 .../core/query/{entity => type}/LogEntity.java     |   2 +-
 .../core/query/{entity => type}/LogState.java      |   2 +-
 .../server/core/query/{entity => type}/Logs.java   |   2 +-
 .../Database.java => type/MetricsValues.java}      |  13 +-
 .../server/core/query/{entity => type}/Node.java   |   2 +-
 .../core/query/{entity => type}/Pagination.java    |   2 +-
 .../query/{entity => type}/ProfileAnalyzation.java |   2 +-
 .../{entity => type}/ProfileAnalyzeTimeRange.java  |   2 +-
 .../{entity => type}/ProfileStackElement.java      |   2 +-
 .../query/{entity => type}/ProfileStackTree.java   |   2 +-
 .../core/query/{entity => type}/ProfileTask.java   |   2 +-
 .../ProfileTaskCreationResult.java                 |   2 +-
 .../query/{entity => type}/ProfileTaskLog.java     |   2 +-
 .../ProfileTaskLogOperationType.java               |   2 +-
 .../query/{entity => type}/ProfiledSegment.java    |   2 +-
 .../core/query/{entity => type}/ProfiledSpan.java  |   2 +-
 .../core/query/{entity => type}/QueryOrder.java    |   2 +-
 .../server/core/query/{entity => type}/Ref.java    |   2 +-
 .../core/query/{entity => type}/RefType.java       |   2 +-
 .../Database.java => type/SelectedRecord.java}     |  27 ++-
 .../core/query/{entity => type}/Service.java       |   2 +-
 .../query/{entity => type}/ServiceInstance.java    |   3 +-
 .../{entity => type}/ServiceInstanceNode.java      |   2 +-
 .../{entity => type}/ServiceInstanceTopology.java  |   2 +-
 .../server/core/query/{entity => type}/Span.java   |   2 +-
 .../Thermodynamic.java}                            |  28 ++-
 .../core/query/{entity => type}/TopNEntity.java    |  15 +-
 .../core/query/{entity => type}/TopNRecord.java    |   6 +-
 .../core/query/{entity => type}/Topology.java      |   2 +-
 .../server/core/query/{entity => type}/Trace.java  |   2 +-
 .../core/query/{entity => type}/TraceBrief.java    |   2 +-
 .../core/query/{entity => type}/TraceState.java    |   2 +-
 .../oap/server/core/source/AbstractLog.java        |   2 +-
 .../oap/server/core/storage/annotation/Column.java |   5 +
 .../storage/annotation/ValueColumnMetadata.java    |  16 +-
 .../oap/server/core/storage/model/ModelColumn.java |   4 +-
 .../server/core/storage/model/StorageModels.java   |   3 +-
 .../storage/profile/IProfileTaskLogQueryDAO.java   |   2 +-
 .../core/storage/profile/IProfileTaskQueryDAO.java |   2 +-
 .../profile/IProfileThreadSnapshotQueryDAO.java    |   2 +-
 .../core/storage/query/IAggregationQueryDAO.java   |  32 +--
 .../server/core/storage/query/IAlarmQueryDAO.java  |   2 +-
 .../server/core/storage/query/ILogQueryDAO.java    |   6 +-
 .../core/storage/query/IMetadataQueryDAO.java      |  15 +-
 .../core/storage/query/IMetricsQueryDAO.java       |  63 ++++-
 .../core/storage/query/ITopNRecordsQueryDAO.java   |  15 +-
 .../core/storage/query/ITopologyQueryDAO.java      |  16 +-
 .../server/core/storage/query/ITraceQueryDAO.java  |   8 +-
 .../storage/type/StorageDataComplexObject.java     |   4 +-
 .../server-core/src/main/proto/RemoteService.proto |  11 +-
 .../core/analysis/metrics/DataTableTestCase.java   |  62 +++++
 ...micMetricsTest.java => HeatMapMetricsTest.java} |  35 ++-
 .../metrics/IntKeyLongValueHashMapTestCase.java    |  68 ------
 .../core/analysis/metrics/PxxMetricsTest.java      |   2 +-
 .../core/profile/analyze/ProfileStackAnalyze.java  |   6 +-
 .../core/profile/analyze/ProfileStackData.java     |   2 +-
 .../analyze/ProfileStackElementMatcher.java        |   4 +-
 .../server/core/storage/model/ModelColumnTest.java |   4 +-
 .../oap/query/graphql/GraphQLQueryProvider.java    |  23 +-
 .../query/graphql/resolver/AggregationQuery.java   | 122 ++++++----
 .../oap/query/graphql/resolver/AlarmQuery.java     |  19 +-
 .../oap/query/graphql/resolver/LogQuery.java       |  20 +-
 .../oap/query/graphql/resolver/MetadataQuery.java  |  47 ++--
 .../oap/query/graphql/resolver/MetricQuery.java    | 163 +++++++++----
 .../oap/query/graphql/resolver/MetricsQuery.java   | 141 +++++++++++
 .../oap/query/graphql/resolver/Mutation.java       |   2 +-
 .../query/graphql/resolver/ProfileMutation.java    |   4 +-
 .../oap/query/graphql/resolver/ProfileQuery.java   |  10 +-
 .../oap/query/graphql/resolver/Query.java          |   2 +-
 .../query/graphql/resolver/TopNRecordsQuery.java   |  58 ++---
 .../oap/query/graphql/resolver/TopologyQuery.java  |  35 +--
 .../oap/query/graphql/resolver/TraceQuery.java     |  23 +-
 .../query/graphql/type/BatchMetricConditions.java  |   4 +-
 .../oap/query/graphql/type/Duration.java           |  29 ---
 .../query/graphql/type/TopNRecordsCondition.java   |   4 +-
 .../src/main/resources/query-protocol              |   2 +-
 .../handler/ProfileTaskServiceHandler.java         |   4 +-
 .../elasticsearch/base/ColumnTypeEsMapping.java    |   4 +-
 .../storage/plugin/elasticsearch/base/EsDAO.java   |  26 --
 .../elasticsearch/query/AggregationQueryEsDAO.java | 122 +++-------
 .../elasticsearch/query/AlarmQueryEsDAO.java       |   6 +-
 .../plugin/elasticsearch/query/LogQueryEsDAO.java  |  10 +-
 .../elasticsearch/query/MetadataQueryEsDAO.java    |  59 +----
 .../elasticsearch/query/MetricsQueryEsDAO.java     | 239 +++++++++++--------
 .../elasticsearch/query/ProfileTaskLogEsDAO.java   |   4 +-
 .../elasticsearch/query/ProfileTaskQueryEsDAO.java |   2 +-
 .../query/ProfileThreadSnapshotQueryEsDAO.java     |   2 +-
 .../elasticsearch/query/TopNRecordsQueryEsDAO.java |  37 ++-
 .../elasticsearch/query/TopologyQueryEsDAO.java    |  18 +-
 .../elasticsearch/query/TraceQueryEsDAO.java       |  10 +-
 .../query/AggregationQueryEs7DAO.java              |  66 +++---
 .../elasticsearch7/query/AlarmQueryEs7DAO.java     |   6 +-
 .../elasticsearch7/query/LogQueryEs7DAO.java       |  10 +-
 .../elasticsearch7/query/MetadataQueryEs7DAO.java  |  50 ----
 .../elasticsearch7/query/MetricsQueryEs7DAO.java   |  50 ++--
 .../elasticsearch7/query/TraceQueryEs7DAO.java     |   8 +-
 .../storage/plugin/influxdb/InfluxClient.java      |   8 -
 .../plugin/influxdb/query/AggregationQuery.java    | 108 +++------
 .../storage/plugin/influxdb/query/AlarmQuery.java  |   6 +-
 .../storage/plugin/influxdb/query/LogQuery.java    |  10 +-
 .../plugin/influxdb/query/MetadataQuery.java       |  45 +---
 .../plugin/influxdb/query/MetricsQuery.java        | 262 ++++++++-------------
 .../plugin/influxdb/query/ProfileTaskLogQuery.java |   4 +-
 .../plugin/influxdb/query/ProfileTaskQuery.java    |   2 +-
 .../influxdb/query/ProfileThreadSnapshotQuery.java |   2 +-
 .../plugin/influxdb/query/TopNRecordsQuery.java    |  44 ++--
 .../plugin/influxdb/query/TopologyQuery.java       |  16 +-
 .../storage/plugin/influxdb/query/TraceQuery.java  |  10 +-
 .../elasticsearch/JaegerTraceQueryEsDAO.java       |  18 +-
 .../plugin/jdbc/h2/dao/H2AggregationQueryDAO.java  | 111 ++-------
 .../plugin/jdbc/h2/dao/H2AlarmQueryDAO.java        |   6 +-
 .../storage/plugin/jdbc/h2/dao/H2LogQueryDAO.java  |  10 +-
 .../plugin/jdbc/h2/dao/H2MetadataQueryDAO.java     |  59 +----
 .../plugin/jdbc/h2/dao/H2MetricsQueryDAO.java      | 223 ++++++++----------
 .../jdbc/h2/dao/H2ProfileTaskLogQueryDAO.java      |   4 +-
 .../plugin/jdbc/h2/dao/H2ProfileTaskQueryDAO.java  |   2 +-
 .../h2/dao/H2ProfileThreadSnapshotQueryDAO.java    |   2 +-
 .../plugin/jdbc/h2/dao/H2TableInstaller.java       |   4 +-
 .../plugin/jdbc/h2/dao/H2TopNRecordsQueryDAO.java  |  43 ++--
 .../plugin/jdbc/h2/dao/H2TopologyQueryDAO.java     |  18 +-
 .../plugin/jdbc/h2/dao/H2TraceQueryDAO.java        |  10 +-
 .../jdbc/mysql/MySQLAggregationQueryDAO.java       |  51 ----
 .../plugin/jdbc/mysql/MySQLAlarmQueryDAO.java      |   6 +-
 .../plugin/jdbc/mysql/MySQLTableInstaller.java     |   4 +-
 .../elasticsearch/ZipkinTraceQueryEsDAO.java       |  22 +-
 .../profile/exporter/ProfileSnapshotDumper.java    |   2 +-
 .../tool/profile/exporter/ProfiledBasicInfo.java   |   6 +-
 .../exporter/ProfileAnalyzeSnapshotDAO.java        |   2 +-
 .../profile/exporter/ProfileExportedAnalyze.java   |  10 +-
 .../exporter/test/ProfileExportSnapshotDAO.java    |   2 +-
 .../exporter/test/ProfileSnapshotExporterTest.java |   2 +-
 .../profile/exporter/test/ProfileTraceDAO.java     |   8 +-
 .../tool/profile/core/MockCoreModuleProvider.java  |   4 +-
 skywalking-ui                                      |   2 +-
 207 files changed, 2458 insertions(+), 2587 deletions(-)

diff --git a/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/parser/AnalysisResult.java b/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/parser/AnalysisResult.java
index b55796f..05419b8 100644
--- a/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/parser/AnalysisResult.java
+++ b/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/parser/AnalysisResult.java
@@ -140,8 +140,8 @@ public class AnalysisResult {
                 case "long":
                     serializeFields.addLongField(column.getFieldName());
                     break;
-                case "IntKeyLongValueHashMap":
-                    serializeFields.addIntKeyLongValueHashMapField(column.getFieldName());
+                case "DataTable":
+                    serializeFields.addDataTableField(column.getFieldName());
                     break;
                 default:
                     throw new IllegalStateException("Unexpected field type [" + type + "] of persistence column [" + column
diff --git a/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/parser/PersistenceColumns.java b/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/parser/PersistenceColumns.java
index d47b7e0..8fbde82 100644
--- a/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/parser/PersistenceColumns.java
+++ b/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/rt/parser/PersistenceColumns.java
@@ -26,7 +26,7 @@ public class PersistenceColumns {
     private List<PersistenceField> longFields = new LinkedList<>();
     private List<PersistenceField> doubleFields = new LinkedList<>();
     private List<PersistenceField> intFields = new LinkedList<>();
-    private List<PersistenceField> intKeyLongValueHashMap = new LinkedList<>();
+    private List<PersistenceField> dataTableFields = new LinkedList<>();
 
     public void addStringField(String fieldName) {
         stringFields.add(new PersistenceField(fieldName));
@@ -44,8 +44,8 @@ public class PersistenceColumns {
         intFields.add(new PersistenceField(fieldName));
     }
 
-    public void addIntKeyLongValueHashMapField(String fieldName) {
-        intKeyLongValueHashMap.add(new PersistenceField(fieldName));
+    public void addDataTableField(String fieldName) {
+        dataTableFields.add(new PersistenceField(fieldName));
     }
 
     public List<PersistenceField> getStringFields() {
@@ -64,7 +64,7 @@ public class PersistenceColumns {
         return intFields;
     }
 
-    public List<PersistenceField> getIntKeyLongValueHashMapFields() {
-        return intKeyLongValueHashMap;
+    public List<PersistenceField> getDataTableFields() {
+        return dataTableFields;
     }
 }
diff --git a/oap-server/oal-rt/src/main/resources/code-templates/metrics/deserialize.ftl b/oap-server/oal-rt/src/main/resources/code-templates/metrics/deserialize.ftl
index de5c4d0..c898403 100644
--- a/oap-server/oal-rt/src/main/resources/code-templates/metrics/deserialize.ftl
+++ b/oap-server/oal-rt/src/main/resources/code-templates/metrics/deserialize.ftl
@@ -15,12 +15,8 @@ public void deserialize(org.apache.skywalking.oap.server.core.remote.grpc.proto.
     ${field.setter}(remoteData.getDataIntegers(${field?index}));
 </#list>
 
-java.util.Iterator iterator;
-<#list serializeFields.intKeyLongValueHashMapFields as field>
-    iterator = remoteData.getDataLists(${field?index}).getValueList().iterator();
-    while (iterator.hasNext()) {
-    org.apache.skywalking.oap.server.core.remote.grpc.proto.IntKeyLongValuePair element = (org.apache.skywalking.oap.server.core.remote.grpc.proto.IntKeyLongValuePair)(iterator.next());
-    super.${field.getter}().put(new Integer(element.getKey()), new org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValue(element.getKey(), element.getValue()));
-    }
+<#list serializeFields.dataTableFields as field>
+    ${field.setter}(new org.apache.skywalking.oap.server.core.analysis.metrics.DataTable(remoteData.getDataTableStrings(${field?index})));
 </#list>
+
 }
\ No newline at end of file
diff --git a/oap-server/oal-rt/src/main/resources/code-templates/metrics/serialize.ftl b/oap-server/oal-rt/src/main/resources/code-templates/metrics/serialize.ftl
index 731f292..657f901 100644
--- a/oap-server/oal-rt/src/main/resources/code-templates/metrics/serialize.ftl
+++ b/oap-server/oal-rt/src/main/resources/code-templates/metrics/serialize.ftl
@@ -15,15 +15,9 @@ org.apache.skywalking.oap.server.core.remote.grpc.proto.RemoteData.Builder remot
 <#list serializeFields.intFields as field>
     remoteBuilder.addDataIntegers(${field.getter}());
 </#list>
-java.util.Iterator iterator;
-org.apache.skywalking.oap.server.core.remote.grpc.proto.DataIntLongPairList.Builder pairListBuilder;
-<#list serializeFields.intKeyLongValueHashMapFields as field>
-    iterator = super.${field.getter}().values().iterator();
-    pairListBuilder = org.apache.skywalking.oap.server.core.remote.grpc.proto.DataIntLongPairList.newBuilder();
-    while (iterator.hasNext()) {
-    pairListBuilder.addValue(((org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValue)(iterator.next())).serialize());
-    }
-    remoteBuilder.addDataLists(pairListBuilder);
+
+<#list serializeFields.dataTableFields as field>
+    remoteBuilder.addDataTableStrings(${field.getter}().toStorageData());
 </#list>
 
 return remoteBuilder;
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPChookCallbackTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPChookCallbackTest.java
index e5cc052..5607dc4 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPChookCallbackTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPChookCallbackTest.java
@@ -23,7 +23,7 @@ import java.util.List;
 import org.apache.skywalking.oap.server.core.alarm.AlarmMessage;
 import org.apache.skywalking.oap.server.core.alarm.provider.AlarmRulesWatcher;
 import org.apache.skywalking.oap.server.core.alarm.provider.Rules;
-import org.apache.skywalking.oap.server.core.query.entity.Scope;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
 import org.junit.Before;
 import org.junit.Test;
 
diff --git a/oap-server/server-bootstrap/src/main/resources/official_analysis.oal b/oap-server/server-bootstrap/src/main/resources/official_analysis.oal
index afee68b..aa9ec4f 100755
--- a/oap-server/server-bootstrap/src/main/resources/official_analysis.oal
+++ b/oap-server/server-bootstrap/src/main/resources/official_analysis.oal
@@ -18,7 +18,7 @@
 
 // All scope metrics
 all_percentile = from(All.latency).percentile(10);  // Multiple values including p50, p75, p90, p95, p99
-all_heatmap = from(All.latency).thermodynamic(100, 20);
+all_heatmap = from(All.latency).histogram(100, 20);
 
 // Service scope metrics
 service_resp_time = from(Service.latency).longAvg();
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java
index 37bc7c8..82450bb 100755
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java
@@ -32,7 +32,7 @@ import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
 import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
 import org.apache.skywalking.oap.server.core.query.LogQueryService;
 import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
-import org.apache.skywalking.oap.server.core.query.MetricQueryService;
+import org.apache.skywalking.oap.server.core.query.MetricsQueryService;
 import org.apache.skywalking.oap.server.core.query.ProfileTaskQueryService;
 import org.apache.skywalking.oap.server.core.query.TopNRecordsQueryService;
 import org.apache.skywalking.oap.server.core.query.TopologyQueryService;
@@ -90,7 +90,7 @@ public class CoreModule extends ModuleDefine {
 
     private void addQueryService(List<Class> classes) {
         classes.add(TopologyQueryService.class);
-        classes.add(MetricQueryService.class);
+        classes.add(MetricsQueryService.class);
         classes.add(TraceQueryService.class);
         classes.add(LogQueryService.class);
         classes.add(MetadataQueryService.class);
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
index c23255c..03a1be7 100755
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
@@ -48,7 +48,7 @@ import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
 import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
 import org.apache.skywalking.oap.server.core.query.LogQueryService;
 import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
-import org.apache.skywalking.oap.server.core.query.MetricQueryService;
+import org.apache.skywalking.oap.server.core.query.MetricsQueryService;
 import org.apache.skywalking.oap.server.core.query.ProfileTaskQueryService;
 import org.apache.skywalking.oap.server.core.query.TopNRecordsQueryService;
 import org.apache.skywalking.oap.server.core.query.TopologyQueryService;
@@ -213,7 +213,7 @@ public class CoreModuleProvider extends ModuleProvider {
             NetworkAddressAliasCache.class, new NetworkAddressAliasCache(moduleConfig));
 
         this.registerServiceImplementation(TopologyQueryService.class, new TopologyQueryService(getManager()));
-        this.registerServiceImplementation(MetricQueryService.class, new MetricQueryService(getManager()));
+        this.registerServiceImplementation(MetricsQueryService.class, new MetricsQueryService(getManager()));
         this.registerServiceImplementation(TraceQueryService.class, new TraceQueryService(getManager()));
         this.registerServiceImplementation(LogQueryService.class, new LogQueryService(getManager()));
         this.registerServiceImplementation(MetadataQueryService.class, new MetadataQueryService(getManager()));
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/IDManager.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/IDManager.java
index 4eb4b47..ccd3670 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/IDManager.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/IDManager.java
@@ -39,8 +39,11 @@ public class IDManager {
          * @return encoded service id
          */
         public static String buildId(String name, NodeType type) {
-            return encode(name) + Const.SERVICE_ID_CONNECTOR + BooleanUtils.booleanToValue(
-                type.equals(NodeType.Normal));
+            return buildId(name, type.equals(NodeType.Normal));
+        }
+
+        public static String buildId(String name, boolean isNormal) {
+            return encode(name) + Const.SERVICE_ID_CONNECTOR + BooleanUtils.booleanToValue(isNormal);
         }
 
         /**
@@ -157,11 +160,11 @@ public class IDManager {
         @EqualsAndHashCode
         public static class ServiceInstanceRelationDefine {
             /**
-             * Built by {@link ServiceID#buildId(String, NodeType)}
+             * Built by {@link ServiceInstanceID#buildId(String, String)}
              */
             private final String sourceId;
             /**
-             * Built by {@link ServiceID#buildId(String, NodeType)}
+             * Built by {@link ServiceInstanceID#buildId(String, String)}
              */
             private final String destId;
         }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/TimeBucket.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/TimeBucket.java
index df604a7..59ea7c4 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/TimeBucket.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/TimeBucket.java
@@ -95,14 +95,6 @@ public class TimeBucket {
     }
 
     /**
-     * The format of timeBucket in month Unit is "yyyyMM", so which means the TimeBucket must be between 100000 and
-     * 999999.
-     */
-    public static boolean isMonthBucket(long timeBucket) {
-        return timeBucket < 999999L && timeBucket > 100000L;
-    }
-
-    /**
      * Convert TimeBucket to Timestamp in millisecond.
      *
      * @param timeBucket   long
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/log/AbstractLogRecord.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/log/AbstractLogRecord.java
index a35da2b..9c435b9 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/log/AbstractLogRecord.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/log/AbstractLogRecord.java
@@ -24,7 +24,7 @@ import lombok.Getter;
 import lombok.Setter;
 import org.apache.skywalking.oap.server.core.UnexpectedException;
 import org.apache.skywalking.oap.server.core.analysis.record.Record;
-import org.apache.skywalking.oap.server.core.query.entity.ContentType;
+import org.apache.skywalking.oap.server.core.query.type.ContentType;
 import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
 import org.apache.skywalking.oap.server.core.storage.annotation.Column;
 
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/DataTable.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/DataTable.java
new file mode 100644
index 0000000..8216f69
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/DataTable.java
@@ -0,0 +1,119 @@
+/*
+ * 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.skywalking.oap.server.core.analysis.metrics;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.skywalking.oap.server.core.Const;
+import org.apache.skywalking.oap.server.core.storage.type.StorageDataComplexObject;
+
+/**
+ * DataTable includes a hashmap to store string key and long value. It enhanced the serialization capability.
+ */
+public class DataTable implements StorageDataComplexObject<DataTable> {
+    private HashMap<String, Long> data;
+
+    public DataTable() {
+        data = new HashMap<>();
+    }
+
+    public DataTable(int initialCapacity) {
+        data = new HashMap<>(initialCapacity);
+    }
+
+    public DataTable(String data) {
+        this();
+        toObject(data);
+    }
+
+    public Long get(String key) {
+        return data.get(key);
+    }
+
+    public void put(String key, Long value) {
+        data.put(key, value);
+    }
+
+    public long sumOfValues() {
+        return data.values().stream().mapToLong(element -> element).sum();
+    }
+
+    public List<String> sortedKeys(Comparator<String> keyComparator) {
+        return data.keySet().stream().sorted(keyComparator).collect(Collectors.toList());
+    }
+
+    public List<Long> sortedValues(Comparator<String> keyComparator) {
+        final List<String> collect = data.keySet().stream().sorted(keyComparator).collect(Collectors.toList());
+        List<Long> values = new ArrayList<>(collect.size());
+        collect.forEach(key -> values.add(data.get(key)));
+        return values;
+    }
+
+    public boolean hasData() {
+        return !data.isEmpty();
+    }
+
+    public int size() {
+        return data.size();
+    }
+
+    @Override
+    public String toStorageData() {
+        StringBuilder builder = new StringBuilder();
+
+        this.data.forEach((key, value) -> {
+            if (builder.length() != 0) {
+                // For the first element.
+                builder.append(Const.ARRAY_SPLIT);
+            }
+            builder.append(key).append(Const.KEY_VALUE_SPLIT).append(value);
+        });
+        return builder.toString();
+    }
+
+    @Override
+    public void toObject(String data) {
+        String[] keyValues = data.split(Const.ARRAY_PARSER_SPLIT);
+        for (String keyValue : keyValues) {
+            final String[] keyValuePair = keyValue.split(Const.KEY_VALUE_SPLIT);
+            if (keyValuePair.length == 2) {
+                this.data.put(keyValuePair[0], Long.parseLong(keyValuePair[1]));
+            }
+        }
+    }
+
+    @Override
+    public void copyFrom(final DataTable source) {
+        this.append(source);
+    }
+
+    public void append(DataTable dataTable) {
+        dataTable.data.forEach((key, value) -> {
+            Long current = this.data.get(key);
+            if (current == null) {
+                current = value;
+            } else {
+                current += value;
+            }
+            this.data.put(key, current);
+        });
+    }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/GroupMetrics.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/GroupMetrics.java
deleted file mode 100644
index c1b818d..0000000
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/GroupMetrics.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.skywalking.oap.server.core.analysis.metrics;
-
-public abstract class GroupMetrics extends Metrics {
-
-    protected void combine(IntKeyLongValueHashMap source, IntKeyLongValueHashMap target) {
-        source.forEach((key, element) -> {
-            IntKeyLongValue existingElement = target.get(key);
-            if (existingElement == null) {
-                target.put(key, new IntKeyLongValue(key, element.getValue()));
-            } else {
-                existingElement.addValue(element.getValue());
-            }
-        });
-    }
-}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/ThermodynamicMetrics.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/HistogramMetrics.java
similarity index 60%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/ThermodynamicMetrics.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/HistogramMetrics.java
index 967f594..12fca97 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/ThermodynamicMetrics.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/HistogramMetrics.java
@@ -27,73 +27,67 @@ import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.SourceF
 import org.apache.skywalking.oap.server.core.storage.annotation.Column;
 
 /**
- * Thermodynamic metrics represents the calculator for heat map.
+ * Histogram metrics represents the calculator for heat map.
  * <p>
  * It groups the given collection of values by the given step and number of steps.
  * <p>
  * A heat map (or heatmap) is a graphical representation of data where the individual values contained in a matrix are
  * represented as colors.
  */
-@MetricsFunction(functionName = "thermodynamic")
-public abstract class ThermodynamicMetrics extends GroupMetrics {
+@MetricsFunction(functionName = "histogram")
+public abstract class HistogramMetrics extends Metrics {
 
-    public static final String DETAIL_GROUP = "detail_group";
-    public static final String STEP = "step";
-    public static final String NUM_OF_STEPS = "num_of_steps";
+    public static final String DATASET = "dataset";
 
-    @Getter
-    @Setter
-    @Column(columnName = STEP, storageOnly = true)
-    private int step = 0;
-    @Getter
-    @Setter
-    @Column(columnName = NUM_OF_STEPS, storageOnly = true)
-    private int numOfSteps = 0;
     /**
-     * The special case when the column is isValue = true, but storageOnly = true, because it is {@link
-     * IntKeyLongValueHashMap} type, this column can't be query by the aggregation way.
+     * The special case when the column is isValue = true, but storageOnly = true, because it is {@link DataTable} type,
+     * this column can't be query by the aggregation way.
      */
     @Getter
     @Setter
-    @Column(columnName = DETAIL_GROUP, isValue = true, storageOnly = true)
-    private IntKeyLongValueHashMap detailGroup = new IntKeyLongValueHashMap(30);
+    @Column(columnName = DATASET, isValue = true, storageOnly = true)
+    private DataTable dataset = new DataTable(30);
 
     /**
      * Data will be grouped in
-     * <p>
-     * [0, step), [step, step * 2), ..., [step * (maxNumOfSteps - 1), step * maxNumOfSteps), [step * maxNumOfSteps,
-     * MAX)
+     * <pre>
+     * key = 0, represents [0, 100), value = count of requests in the latency range.
+     * key = 100, represents [100, 200), value = count of requests in the latency range.
+     * ...
+     * key = step * maxNumOfSteps, represents [step * maxNumOfSteps, MAX)
+     * </pre>
      *
      * @param step          the size of each step. A positive integer.
      * @param maxNumOfSteps Steps are used to group incoming value.
      */
     @Entrance
     public final void combine(@SourceFrom int value, @Arg int step, @Arg int maxNumOfSteps) {
-        if (this.step == 0) {
-            this.step = step;
-        }
-        if (this.numOfSteps == 0) {
-            this.numOfSteps = maxNumOfSteps;
+        if (!dataset.hasData()) {
+            for (int i = 0; i <= maxNumOfSteps; i++) {
+                String key = String.valueOf(i * step);
+                dataset.put(key, 0L);
+            }
         }
 
         int index = value / step;
         if (index > maxNumOfSteps) {
-            index = numOfSteps;
+            index = maxNumOfSteps;
         }
+        String idx = String.valueOf(index * step);
 
-        IntKeyLongValue element = detailGroup.get(index);
+        Long element = dataset.get(idx);
         if (element == null) {
-            element = new IntKeyLongValue(index, 1);
-            detailGroup.put(element.getKey(), element);
+            element = 1L;
         } else {
-            element.addValue(1);
+            element++;
         }
+        dataset.put(idx, element);
     }
 
     @Override
     public void combine(Metrics metrics) {
-        ThermodynamicMetrics thermodynamicMetrics = (ThermodynamicMetrics) metrics;
-        combine(thermodynamicMetrics.getDetailGroup(), this.detailGroup);
+        HistogramMetrics histogramMetrics = (HistogramMetrics) metrics;
+        this.dataset.append(histogramMetrics.dataset);
     }
 
     /**
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/IntKeyLongValue.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/IntKeyLongValue.java
deleted file mode 100644
index c7fb477..0000000
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/IntKeyLongValue.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.skywalking.oap.server.core.analysis.metrics;
-
-import java.util.Objects;
-import lombok.Getter;
-import lombok.Setter;
-import org.apache.skywalking.oap.server.core.Const;
-import org.apache.skywalking.oap.server.core.remote.grpc.proto.IntKeyLongValuePair;
-import org.apache.skywalking.oap.server.core.storage.type.StorageDataComplexObject;
-
-/**
- * IntKeyLongValue is a common bean, with key in Int and value in Long
- */
-@Setter
-@Getter
-public class IntKeyLongValue implements Comparable<IntKeyLongValue>, StorageDataComplexObject {
-    private int key;
-    private long value;
-
-    public IntKeyLongValue() {
-    }
-
-    public IntKeyLongValue(int key, long value) {
-        this.key = key;
-        this.value = value;
-    }
-
-    public void addValue(long value) {
-        this.value += value;
-    }
-
-    @Override
-    public int compareTo(IntKeyLongValue o) {
-        return key - o.key;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o)
-            return true;
-        if (o == null || getClass() != o.getClass())
-            return false;
-        IntKeyLongValue value = (IntKeyLongValue) o;
-        return key == value.key;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(key);
-    }
-
-    public IntKeyLongValuePair serialize() {
-        return IntKeyLongValuePair.newBuilder().setKey(key).setValue(value).build();
-    }
-
-    public void deserialize(IntKeyLongValuePair pair) {
-        this.key = pair.getKey();
-        this.value = pair.getValue();
-    }
-
-    @Override
-    public String toStorageData() {
-        return key + Const.KEY_VALUE_SPLIT + value;
-    }
-
-    @Override
-    public void toObject(String data) {
-        String[] keyValue = data.split(Const.KEY_VALUE_SPLIT);
-        this.key = Integer.parseInt(keyValue[0]);
-        this.value = Long.parseLong(keyValue[1]);
-    }
-
-    @Override
-    public void copyFrom(Object source) {
-        IntKeyLongValue value = (IntKeyLongValue) source;
-        this.key = value.key;
-        this.value = value.value;
-    }
-}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/IntKeyLongValueHashMap.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/IntKeyLongValueHashMap.java
deleted file mode 100644
index a7ed6db..0000000
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/IntKeyLongValueHashMap.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.skywalking.oap.server.core.analysis.metrics;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.apache.skywalking.oap.server.core.Const;
-import org.apache.skywalking.oap.server.core.storage.type.StorageDataComplexObject;
-
-public class IntKeyLongValueHashMap extends HashMap<Integer, IntKeyLongValue> implements StorageDataComplexObject {
-
-    public IntKeyLongValueHashMap() {
-        super();
-    }
-
-    public IntKeyLongValueHashMap(int initialCapacity) {
-        super(initialCapacity);
-    }
-
-    public IntKeyLongValueHashMap(String data) {
-        super();
-        toObject(data);
-    }
-
-    @Override
-    public String toStorageData() {
-        StringBuilder data = new StringBuilder();
-
-        List<Map.Entry<Integer, IntKeyLongValue>> list = new ArrayList<>(this.entrySet());
-
-        for (int i = 0; i < list.size(); i++) {
-            if (i == 0) {
-                data.append(list.get(i).getValue().toStorageData());
-            } else {
-                data.append(Const.ARRAY_SPLIT).append(list.get(i).getValue().toStorageData());
-            }
-        }
-        return data.toString();
-    }
-
-    @Override
-    public void toObject(String data) {
-        String[] keyValues = data.split(Const.ARRAY_PARSER_SPLIT);
-        for (String keyValue : keyValues) {
-            IntKeyLongValue value = new IntKeyLongValue();
-            value.toObject(keyValue);
-            this.put(value.getKey(), value);
-        }
-    }
-
-    @Override
-    public void copyFrom(Object source) {
-        IntKeyLongValueHashMap intKeyLongValueHashMap = (IntKeyLongValueHashMap) source;
-        intKeyLongValueHashMap.values().forEach(value -> {
-            IntKeyLongValue newValue = new IntKeyLongValue();
-            newValue.copyFrom(value);
-            this.put(newValue.getKey(), newValue);
-        });
-    }
-}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Language.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/MetricsRegister.java
similarity index 81%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Language.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/MetricsRegister.java
index ae8d83a..fd64fca 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Language.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/MetricsRegister.java
@@ -16,8 +16,12 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.analysis.metrics;
 
-public enum Language {
-    UNKNOWN, JAVA, DOTNET, NODEJS, PYTHON, RUBY, GO, LUA, PHP
+/**
+ * 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/analysis/metrics/PercentileMetrics.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/PercentileMetrics.java
index 8c8962b..ac3889d 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/PercentileMetrics.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/PercentileMetrics.java
@@ -19,6 +19,8 @@
 package org.apache.skywalking.oap.server.core.analysis.metrics;
 
 import java.util.Comparator;
+import java.util.List;
+import java.util.stream.IntStream;
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Arg;
@@ -32,7 +34,7 @@ import org.apache.skywalking.oap.server.core.storage.annotation.Column;
  * multiple P50/75/90/95/99 values once for all.
  */
 @MetricsFunction(functionName = "percentile")
-public abstract class PercentileMetrics extends GroupMetrics implements MultiIntValuesHolder {
+public abstract class PercentileMetrics extends Metrics implements MultiIntValuesHolder {
     protected static final String DATASET = "dataset";
     protected static final String VALUE = "value";
     protected static final String PRECISION = "precision";
@@ -46,13 +48,13 @@ public abstract class PercentileMetrics extends GroupMetrics implements MultiInt
     };
 
     /**
-     * The special case when the column is isValue = true, but storageOnly = true, because it is {@link
-     * IntKeyLongValueHashMap} type, this column can't be query by the aggregation way.
+     * The special case when the column is isValue = true, but storageOnly = true, because it is {@link DataTable} type,
+     * this column can't be query by the aggregation way.
      */
     @Getter
     @Setter
     @Column(columnName = VALUE, isValue = true, storageOnly = true)
-    private IntKeyLongValueHashMap percentileValues;
+    private DataTable percentileValues;
     @Getter
     @Setter
     @Column(columnName = PRECISION, storageOnly = true)
@@ -60,13 +62,13 @@ public abstract class PercentileMetrics extends GroupMetrics implements MultiInt
     @Getter
     @Setter
     @Column(columnName = DATASET, storageOnly = true)
-    private IntKeyLongValueHashMap dataset;
+    private DataTable dataset;
 
     private boolean isCalculated;
 
     public PercentileMetrics() {
-        percentileValues = new IntKeyLongValueHashMap(RANKS.length);
-        dataset = new IntKeyLongValueHashMap(30);
+        percentileValues = new DataTable(RANKS.length);
+        dataset = new DataTable(30);
     }
 
     @Entrance
@@ -74,14 +76,14 @@ public abstract class PercentileMetrics extends GroupMetrics implements MultiInt
         this.isCalculated = false;
         this.precision = precision;
 
-        int index = value / precision;
-        IntKeyLongValue element = dataset.get(index);
+        String index = String.valueOf(value / precision);
+        Long element = dataset.get(index);
         if (element == null) {
-            element = new IntKeyLongValue(index, 1);
-            dataset.put(element.getKey(), element);
+            element = 1L;
         } else {
-            element.addValue(1);
+            element++;
         }
+        dataset.put(index, element);
     }
 
     @Override
@@ -89,34 +91,33 @@ public abstract class PercentileMetrics extends GroupMetrics implements MultiInt
         this.isCalculated = false;
 
         PercentileMetrics percentileMetrics = (PercentileMetrics) metrics;
-        combine(percentileMetrics.getDataset(), this.dataset);
+        this.dataset.append(percentileMetrics.dataset);
     }
 
     @Override
     public final void calculate() {
-
         if (!isCalculated) {
-            int total = dataset.values().stream().mapToInt(element -> (int) element.getValue()).sum();
+            long total = dataset.sumOfValues();
 
-            int index = 0;
             int[] roofs = new int[RANKS.length];
             for (int i = 0; i < RANKS.length; i++) {
                 roofs[i] = Math.round(total * RANKS[i] * 1.0f / 100);
             }
 
             int count = 0;
-            IntKeyLongValue[] sortedData = dataset.values()
-                                                  .stream()
-                                                  .sorted(Comparator.comparingInt(IntKeyLongValue::getKey))
-                                                  .toArray(IntKeyLongValue[]::new);
-            for (IntKeyLongValue element : sortedData) {
-                count += element.getValue();
-                for (int i = index; i < roofs.length; i++) {
-                    int roof = roofs[i];
+            final List<String> sortedKeys = dataset.sortedKeys(Comparator.comparingInt(Integer::parseInt));
+
+            int loopIndex = 0;
+            for (String key : sortedKeys) {
+                final Long value = dataset.get(key);
+
+                count += value;
+                for (int rankIdx = loopIndex; rankIdx < roofs.length; rankIdx++) {
+                    int roof = roofs[rankIdx];
 
                     if (count >= roof) {
-                        percentileValues.put(index, new IntKeyLongValue(index, element.getKey() * precision));
-                        index++;
+                        percentileValues.put(String.valueOf(rankIdx), Long.parseLong(key) * precision);
+                        loopIndex++;
                     } else {
                         break;
                     }
@@ -126,10 +127,9 @@ public abstract class PercentileMetrics extends GroupMetrics implements MultiInt
     }
 
     public int[] getValues() {
-        int[] values = new int[percentileValues.size()];
-        for (int i = 0; i < values.length; i++) {
-            values[i] = (int) percentileValues.get(i).getValue();
-        }
-        return values;
+        return percentileValues.sortedValues(Comparator.comparingInt(Integer::parseInt))
+                               .stream()
+                               .flatMapToInt(l -> IntStream.of(l.intValue()))
+                               .toArray();
     }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/PxxMetrics.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/PxxMetrics.java
index 9674eec..1f4f5c5 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/PxxMetrics.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/PxxMetrics.java
@@ -19,6 +19,7 @@
 package org.apache.skywalking.oap.server.core.analysis.metrics;
 
 import java.util.Comparator;
+import java.util.List;
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Arg;
@@ -34,7 +35,7 @@ import org.apache.skywalking.oap.server.core.storage.annotation.Column;
  * observations in a group of observations fall. For example, the 20th percentile is the value (or score) below which
  * 20% of the observations may be found.
  */
-public abstract class PxxMetrics extends GroupMetrics implements IntValueHolder {
+public abstract class PxxMetrics extends Metrics implements IntValueHolder {
 
     protected static final String DETAIL_GROUP = "detail_group";
     protected static final String VALUE = "value";
@@ -51,14 +52,14 @@ public abstract class PxxMetrics extends GroupMetrics implements IntValueHolder
     @Getter
     @Setter
     @Column(columnName = DETAIL_GROUP, storageOnly = true)
-    private IntKeyLongValueHashMap detailGroup;
+    private DataTable detailGroup;
 
     private final int percentileRank;
     private boolean isCalculated;
 
     public PxxMetrics(int percentileRank) {
         this.percentileRank = percentileRank;
-        detailGroup = new IntKeyLongValueHashMap(30);
+        detailGroup = new DataTable(30);
     }
 
     @Entrance
@@ -66,14 +67,14 @@ public abstract class PxxMetrics extends GroupMetrics implements IntValueHolder
         this.isCalculated = false;
         this.precision = precision;
 
-        int index = value / precision;
-        IntKeyLongValue element = detailGroup.get(index);
+        String index = String.valueOf(value / precision);
+        Long element = detailGroup.get(index);
         if (element == null) {
-            element = new IntKeyLongValue(index, 1);
-            detailGroup.put(element.getKey(), element);
+            element = 1L;
         } else {
-            element.addValue(1);
+            element++;
         }
+        detailGroup.put(index, element);
     }
 
     @Override
@@ -81,27 +82,24 @@ public abstract class PxxMetrics extends GroupMetrics implements IntValueHolder
         this.isCalculated = false;
 
         PxxMetrics pxxMetrics = (PxxMetrics) metrics;
-        combine(pxxMetrics.getDetailGroup(), this.detailGroup);
+        this.detailGroup.append(pxxMetrics.detailGroup);
     }
 
     @Override
     public final void calculate() {
 
         if (!isCalculated) {
-            int total = detailGroup.values().stream().mapToInt(element -> (int) element.getValue()).sum();
+            long total = detailGroup.sumOfValues();
             int roof = Math.round(total * percentileRank * 1.0f / 100);
 
-            int count = 0;
-            IntKeyLongValue[] sortedData = detailGroup.values().stream().sorted(new Comparator<IntKeyLongValue>() {
-                @Override
-                public int compare(IntKeyLongValue o1, IntKeyLongValue o2) {
-                    return o1.getKey() - o2.getKey();
-                }
-            }).toArray(IntKeyLongValue[]::new);
-            for (IntKeyLongValue element : sortedData) {
-                count += element.getValue();
+            long count = 0;
+            final List<String> sortedKeys = detailGroup.sortedKeys(Comparator.comparingInt(Integer::parseInt));
+
+            for (String index : sortedKeys) {
+                final Long value = detailGroup.get(index);
+                count += value;
                 if (count >= roof) {
-                    value = element.getKey() * precision;
+                    this.value = Integer.parseInt(index) * precision;
                     return;
                 }
             }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/cache/CacheUpdateTimer.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/cache/CacheUpdateTimer.java
index 5c02dca..1a3033a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/cache/CacheUpdateTimer.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/cache/CacheUpdateTimer.java
@@ -28,7 +28,7 @@ import org.apache.skywalking.apm.util.RunnableWithExceptionProtection;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
 import org.apache.skywalking.oap.server.core.analysis.manual.networkalias.NetworkAddressAlias;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasDAO;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/cache/ProfileTaskCache.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/cache/ProfileTaskCache.java
index 5ac6fcf..f758961 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/cache/ProfileTaskCache.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/cache/ProfileTaskCache.java
@@ -28,7 +28,7 @@ import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 import org.apache.skywalking.oap.server.core.CoreModuleConfig;
 import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/command/CommandService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/command/CommandService.java
index 64c55b1..ae0a724 100755
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/command/CommandService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/command/CommandService.java
@@ -20,7 +20,7 @@ package org.apache.skywalking.oap.server.core.command;
 
 import java.util.UUID;
 import org.apache.skywalking.apm.network.trace.component.command.ProfileTaskCommand;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 import org.apache.skywalking.oap.server.library.module.Service;
 
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskMutationService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskMutationService.java
index 71ab5d4..202d4c7 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskMutationService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskMutationService.java
@@ -26,8 +26,8 @@ import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.DownSampling;
 import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
 import org.apache.skywalking.oap.server.core.analysis.worker.NoneStreamingProcessor;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskCreationResult;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskCreationResult;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzeCollector.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzeCollector.java
index 8645df3..387b8f9 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzeCollector.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzeCollector.java
@@ -26,7 +26,7 @@ import java.util.function.BinaryOperator;
 import java.util.function.Function;
 import java.util.function.Supplier;
 import java.util.stream.Collector;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileStackTree;
+import org.apache.skywalking.oap.server.core.query.type.ProfileStackTree;
 
 /**
  * Work for {@link ProfileAnalyzer} to analyze.
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java
index 2ac3371..40d61d2 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java
@@ -28,9 +28,9 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzation;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileStackTree;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzation;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzeTimeRange;
+import org.apache.skywalking.oap.server.core.query.type.ProfileStackTree;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackNode.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackNode.java
index 5e0313f..4da2e73 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackNode.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackNode.java
@@ -25,8 +25,8 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.function.Consumer;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileStackElement;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileStackTree;
+import org.apache.skywalking.oap.server.core.query.type.ProfileStackElement;
+import org.apache.skywalking.oap.server.core.query.type.ProfileStackTree;
 
 /**
  * Work for profiling stacks, intermediate state of the {@link ProfileStackElement} and {@link ProfileStack}
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 a2bbccc..40a4c82 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.Const;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
-import org.apache.skywalking.oap.server.core.query.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNEntity;
+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,31 @@ 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 condition, Duration duration) throws IOException {
+        final String valueCName = ValueColumnMetadata.INSTANCE.getValueCName(condition.getName());
+        List<KeyValue> additionalConditions = null;
+        if (StringUtil.isNotEmpty(condition.getParentService())) {
+            additionalConditions = new ArrayList<>(1);
+            final String serviceId = IDManager.ServiceID.buildId(condition.getParentService(), condition.isNormal());
+            additionalConditions.add(new KeyValue(InstanceTraffic.SERVICE_ID, serviceId));
         }
-        return topNEntities;
+        final List<SelectedRecord> selectedRecords = getAggregationQueryDAO().sortMetrics(
+            condition, valueCName, duration, additionalConditions);
+        selectedRecords.forEach(selectedRecord -> {
+            switch (condition.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.EndpointID.analysisId(selectedRecord.getId()).getEndpointName());
+                    break;
+                default:
+                    selectedRecord.setName(Const.UNKNOWN);
+            }
+        });
+        return selectedRecords;
     }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AlarmQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AlarmQueryService.java
index e2f65e5..2b8bdb9 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AlarmQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/AlarmQueryService.java
@@ -19,8 +19,8 @@
 package org.apache.skywalking.oap.server.core.query;
 
 import java.io.IOException;
-import org.apache.skywalking.oap.server.core.query.entity.Alarms;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.Alarms;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
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 8fea8bd..3506318 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
@@ -22,8 +22,7 @@ import java.util.LinkedList;
 import java.util.List;
 import org.apache.skywalking.oap.server.core.Const;
 import org.apache.skywalking.oap.server.core.UnexpectedException;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
-import org.apache.skywalking.oap.server.core.query.entity.Step;
+import org.apache.skywalking.oap.server.core.query.enumeration.Step;
 import org.joda.time.DateTime;
 import org.joda.time.format.DateTimeFormat;
 import org.joda.time.format.DateTimeFormatter;
@@ -41,7 +40,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 +54,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,21 +73,62 @@ 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;
     }
 
+    public List<PointOfTime> getDurationPoints(Step step, long startTimeBucket, long endTimeBucket) {
+        DateTime dateTime = parseToDateTime(step, startTimeBucket);
+
+        List<PointOfTime> durations = new LinkedList<>();
+        durations.add(new PointOfTime(startTimeBucket));
+
+        int i = 0;
+        do {
+            switch (step) {
+                case DAY:
+                    dateTime = dateTime.plusDays(1);
+                    String timeBucket = YYYYMMDD.print(dateTime);
+                    durations.add(new PointOfTime(Long.parseLong(timeBucket)));
+                    break;
+                case HOUR:
+                    dateTime = dateTime.plusHours(1);
+                    timeBucket = YYYYMMDDHH.print(dateTime);
+                    durations.add(new PointOfTime(Long.parseLong(timeBucket)));
+                    break;
+                case MINUTE:
+                    dateTime = dateTime.plusMinutes(1);
+                    timeBucket = YYYYMMDDHHMM.print(dateTime);
+                    durations.add(new PointOfTime(Long.parseLong(timeBucket)));
+                    break;
+                case SECOND:
+                    dateTime = dateTime.plusSeconds(1);
+                    timeBucket = YYYYMMDDHHMMSS.print(dateTime);
+                    durations.add(new PointOfTime(Long.parseLong(timeBucket)));
+                    break;
+            }
+            i++;
+            if (i > 500) {
+                throw new UnexpectedException(
+                    "Duration data error, step: " + step.name() + ", start: " + startTimeBucket + ", end: " + endTimeBucket);
+            }
+        }
+        while (endTimeBucket != durations.get(durations.size() - 1).getPoint());
+
+        return durations;
+    }
+
     public long startTimeToTimestamp(Step step, String dateStr) {
         switch (step) {
             case DAY:
@@ -113,92 +157,17 @@ public enum DurationUtils {
         throw new UnexpectedException("Unsupported step " + step.name());
     }
 
-    public int minutesBetween(DownSampling downsampling, DateTime dateTime) {
-        switch (downsampling) {
-            case Day:
-                return 24 * 60;
-            case Hour:
-                return 60;
-            default:
-                return 1;
-        }
-    }
-
-    public int secondsBetween(DownSampling downsampling, DateTime dateTime) {
-        switch (downsampling) {
-            case Day:
-                return 24 * 60 * 60;
-            case Hour:
-                return 60 * 60;
-            case Minute:
-                return 60;
-            default:
-                return 1;
-        }
-    }
-
-    public List<DurationPoint> getDurationPoints(DownSampling downsampling, long startTimeBucket, long endTimeBucket) {
-        DateTime dateTime = parseToDateTime(downsampling, startTimeBucket);
-
-        List<DurationPoint> durations = new LinkedList<>();
-        durations.add(new DurationPoint(startTimeBucket, secondsBetween(downsampling, dateTime),
-                                        minutesBetween(downsampling, dateTime)
-        ));
-
-        int i = 0;
-        do {
-            switch (downsampling) {
-                case Day:
-                    dateTime = dateTime.plusDays(1);
-                    String timeBucket = YYYYMMDD.print(dateTime);
-                    durations.add(new DurationPoint(Long.parseLong(timeBucket), secondsBetween(downsampling, dateTime),
-                                                    minutesBetween(downsampling, dateTime)
-                    ));
-                    break;
-                case Hour:
-                    dateTime = dateTime.plusHours(1);
-                    timeBucket = YYYYMMDDHH.print(dateTime);
-                    durations.add(new DurationPoint(Long.parseLong(timeBucket), secondsBetween(downsampling, dateTime),
-                                                    minutesBetween(downsampling, dateTime)
-                    ));
-                    break;
-                case Minute:
-                    dateTime = dateTime.plusMinutes(1);
-                    timeBucket = YYYYMMDDHHMM.print(dateTime);
-                    durations.add(new DurationPoint(Long.parseLong(timeBucket), secondsBetween(downsampling, dateTime),
-                                                    minutesBetween(downsampling, dateTime)
-                    ));
-                    break;
-                case Second:
-                    dateTime = dateTime.plusSeconds(1);
-                    timeBucket = YYYYMMDDHHMMSS.print(dateTime);
-                    durations.add(new DurationPoint(Long.parseLong(timeBucket), secondsBetween(downsampling, dateTime),
-                                                    minutesBetween(downsampling, dateTime)
-                    ));
-                    break;
-            }
-            i++;
-            if (i > 500) {
-                throw new UnexpectedException(
-                    "Duration data error, step: " + downsampling.name() + ", start: " + startTimeBucket + ", end: " + endTimeBucket);
-            }
-        }
-        while (endTimeBucket != durations.get(durations.size() - 1).getPoint());
-
-        return durations;
-    }
-
-    private DateTime parseToDateTime(DownSampling downsampling, long time) {
-        switch (downsampling) {
-            case Day:
+    private DateTime parseToDateTime(Step step, long time) {
+        switch (step) {
+            case DAY:
                 return YYYYMMDD.parseDateTime(String.valueOf(time));
-            case Hour:
+            case HOUR:
                 return YYYYMMDDHH.parseDateTime(String.valueOf(time));
-            case Minute:
+            case MINUTE:
                 return YYYYMMDDHHMM.parseDateTime(String.valueOf(time));
-            case Second:
+            case SECOND:
                 return YYYYMMDDHHMMSS.parseDateTime(String.valueOf(time));
         }
-        throw new UnexpectedException("Unexpected downsampling: " + downsampling.name());
+        throw new UnexpectedException("Unexpected downsampling: " + step.name());
     }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/LogQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/LogQueryService.java
index 821a4cb..3ea9f4d 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/LogQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/LogQueryService.java
@@ -21,9 +21,9 @@ package org.apache.skywalking.oap.server.core.query;
 import java.io.IOException;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
-import org.apache.skywalking.oap.server.core.query.entity.LogState;
-import org.apache.skywalking.oap.server.core.query.entity.Logs;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.LogState;
+import org.apache.skywalking.oap.server.core.query.type.Logs;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java
index c5d8698..b373fe4 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java
@@ -21,13 +21,11 @@ package org.apache.skywalking.oap.server.core.query;
 import java.io.IOException;
 import java.util.List;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
-import org.apache.skywalking.oap.server.core.query.entity.ClusterBrief;
-import org.apache.skywalking.oap.server.core.query.entity.Database;
-import org.apache.skywalking.oap.server.core.query.entity.Endpoint;
-import org.apache.skywalking.oap.server.core.query.entity.EndpointInfo;
-import org.apache.skywalking.oap.server.core.query.entity.Service;
-import org.apache.skywalking.oap.server.core.query.entity.ServiceInstance;
-import org.apache.skywalking.oap.server.core.analysis.NodeType;
+import org.apache.skywalking.oap.server.core.query.type.Database;
+import org.apache.skywalking.oap.server.core.query.type.Endpoint;
+import org.apache.skywalking.oap.server.core.query.type.EndpointInfo;
+import org.apache.skywalking.oap.server.core.query.type.Service;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstance;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
@@ -48,16 +46,6 @@ public class MetadataQueryService implements org.apache.skywalking.oap.server.li
         return metadataQueryDAO;
     }
 
-    public ClusterBrief getGlobalBrief(final long startTimestamp, final long endTimestamp) throws IOException {
-        ClusterBrief clusterBrief = new ClusterBrief();
-        clusterBrief.setNumOfService(getMetadataQueryDAO().numOfService(startTimestamp, endTimestamp));
-        clusterBrief.setNumOfEndpoint(getMetadataQueryDAO().numOfEndpoint());
-        clusterBrief.setNumOfDatabase(getMetadataQueryDAO().numOfConjectural(NodeType.Database.value()));
-        clusterBrief.setNumOfCache(getMetadataQueryDAO().numOfConjectural(NodeType.Cache.value()));
-        clusterBrief.setNumOfMQ(getMetadataQueryDAO().numOfConjectural(NodeType.MQ.value()));
-        return clusterBrief;
-    }
-
     public List<Service> getAllServices(final long startTimestamp, final long endTimestamp) throws IOException {
         return getMetadataQueryDAO().getAllServices(startTimestamp, endTimestamp);
     }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetricQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetricQueryService.java
deleted file mode 100644
index 8a2a20c..0000000
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetricQueryService.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.skywalking.oap.server.core.query;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.apache.skywalking.apm.util.StringUtil;
-import org.apache.skywalking.oap.server.core.Const;
-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.entity.IntValues;
-import org.apache.skywalking.oap.server.core.query.entity.Thermodynamic;
-import org.apache.skywalking.oap.server.core.query.sql.KeyValues;
-import org.apache.skywalking.oap.server.core.query.sql.Where;
-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.IMetricsQueryDAO;
-import org.apache.skywalking.oap.server.library.module.ModuleManager;
-import org.apache.skywalking.oap.server.library.module.Service;
-import org.apache.skywalking.oap.server.library.util.CollectionUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class MetricQueryService implements Service {
-
-    private static final Logger logger = LoggerFactory.getLogger(MetricQueryService.class);
-
-    private final ModuleManager moduleManager;
-    private IMetricsQueryDAO metricQueryDAO;
-
-    public MetricQueryService(ModuleManager moduleManager) {
-        this.moduleManager = moduleManager;
-    }
-
-    private IMetricsQueryDAO getMetricQueryDAO() {
-        if (metricQueryDAO == null) {
-            metricQueryDAO = moduleManager.find(StorageModule.NAME).provider().getService(IMetricsQueryDAO.class);
-        }
-        return metricQueryDAO;
-    }
-
-    public IntValues getValues(final String metricsName, final List<String> ids, final DownSampling downsampling,
-        final long startTB, final long endTB) throws IOException {
-        if (CollectionUtils.isEmpty(ids)) {
-            /*
-             * Don't support query values w/o ID. but UI still did this(as bug),
-             * we return an empty list, and a debug level log,
-             * rather than an exception, which always being considered as a serious error from new users.
-             */
-            logger.debug("query metrics[{}] w/o IDs", metricsName);
-            return new IntValues();
-        }
-
-        Where where = new Where();
-        KeyValues intKeyValues = new KeyValues();
-        intKeyValues.setKey(Metrics.ENTITY_ID);
-        where.getKeyValues().add(intKeyValues);
-        ids.forEach(intKeyValues.getValues()::add);
-
-        return getMetricQueryDAO().getValues(metricsName, downsampling, startTB, endTB, where, ValueColumnMetadata.INSTANCE.getValueCName(metricsName), ValueColumnMetadata.INSTANCE
-            .getValueFunction(metricsName));
-    }
-
-    public IntValues getLinearIntValues(final String indName, final String id, final DownSampling downsampling,
-        final long startTB, final long endTB) throws IOException {
-        List<DurationPoint> durationPoints = DurationUtils.INSTANCE.getDurationPoints(downsampling, startTB, endTB);
-        List<String> ids = new ArrayList<>();
-        if (StringUtil.isEmpty(id)) {
-            durationPoints.forEach(durationPoint -> ids.add(String.valueOf(durationPoint.getPoint())));
-        } else {
-            durationPoints.forEach(durationPoint -> ids.add(durationPoint.getPoint() + Const.ID_CONNECTOR + id));
-        }
-
-        return getMetricQueryDAO().getLinearIntValues(indName, downsampling, ids, ValueColumnMetadata.INSTANCE.getValueCName(indName));
-    }
-
-    public List<IntValues> getMultipleLinearIntValues(final String indName, final String id, final int numOfLinear,
-                                                      final DownSampling downsampling, final long startTB, final long endTB) throws IOException {
-        List<Integer> linearIndex = new ArrayList<>(numOfLinear);
-        for (int i = 0; i < numOfLinear; i++) {
-            linearIndex.add(i);
-        }
-
-        return getSubsetOfMultipleLinearIntValues(indName, id, linearIndex, downsampling, startTB, endTB);
-    }
-
-    public List<IntValues> getSubsetOfMultipleLinearIntValues(final String indName, final String id,
-                                                              final List<Integer> linearIndex, final DownSampling downsampling, final long startTB,
-                                                              final long endTB) throws IOException {
-        List<DurationPoint> durationPoints = DurationUtils.INSTANCE.getDurationPoints(downsampling, startTB, endTB);
-        List<String> ids = new ArrayList<>();
-        if (StringUtil.isEmpty(id)) {
-            durationPoints.forEach(durationPoint -> ids.add(String.valueOf(durationPoint.getPoint())));
-        } else {
-            durationPoints.forEach(durationPoint -> ids.add(durationPoint.getPoint() + Const.ID_CONNECTOR + id));
-        }
-
-        IntValues[] multipleLinearIntValues = getMetricQueryDAO().getMultipleLinearIntValues(indName, downsampling, ids, linearIndex, ValueColumnMetadata.INSTANCE
-            .getValueCName(indName));
-
-        List<IntValues> response = new ArrayList<>(linearIndex.size());
-        Collections.addAll(response, multipleLinearIntValues);
-        return response;
-    }
-
-    public Thermodynamic getThermodynamic(final String indName, final String id, final DownSampling downsampling,
-        final long startTB, final long endTB) throws IOException {
-        List<DurationPoint> durationPoints = DurationUtils.INSTANCE.getDurationPoints(downsampling, startTB, endTB);
-        List<String> ids = new ArrayList<>();
-        durationPoints.forEach(durationPoint -> {
-            if (id == null) {
-                ids.add(String.valueOf(durationPoint.getPoint()));
-            } else {
-                ids.add(durationPoint.getPoint() + Const.ID_CONNECTOR + id);
-            }
-        });
-
-        return getMetricQueryDAO().getThermodynamic(indName, downsampling, ids, ValueColumnMetadata.INSTANCE.getValueCName(indName));
-    }
-}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetricsQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetricsQueryService.java
new file mode 100644
index 0000000..f44952c
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetricsQueryService.java
@@ -0,0 +1,85 @@
+/*
+ * 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.skywalking.oap.server.core.query;
+
+import java.io.IOException;
+import java.util.List;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.MetricsCondition;
+import org.apache.skywalking.oap.server.core.query.type.HeatMap;
+import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
+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.IMetricsQueryDAO;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
+import org.apache.skywalking.oap.server.library.module.Service;
+
+@Slf4j
+public class MetricsQueryService implements Service {
+    private final ModuleManager moduleManager;
+    private IMetricsQueryDAO metricQueryDAO;
+
+    public MetricsQueryService(ModuleManager moduleManager) {
+        this.moduleManager = moduleManager;
+    }
+
+    private IMetricsQueryDAO getMetricQueryDAO() {
+        if (metricQueryDAO == null) {
+            metricQueryDAO = moduleManager.find(StorageModule.NAME).provider().getService(IMetricsQueryDAO.class);
+        }
+        return metricQueryDAO;
+    }
+
+    /**
+     * Read metrics single value in the duration of required metrics
+     */
+    public int readMetricsValue(MetricsCondition condition, Duration duration) throws IOException {
+        return getMetricQueryDAO().readMetricsValue(
+            condition, ValueColumnMetadata.INSTANCE.getValueCName(condition.getName()), duration);
+    }
+
+    /**
+     * Read time-series values in the duration of required metrics
+     */
+    public MetricsValues readMetricsValues(MetricsCondition condition, Duration duration) throws IOException {
+        return getMetricQueryDAO().readMetricsValues(
+            condition, ValueColumnMetadata.INSTANCE.getValueCName(condition.getName()), duration);
+    }
+
+    /**
+     * Read value in the given time duration, usually as a linear.
+     *
+     * @param labels the labels you need to query.
+     */
+    public List<MetricsValues> readLabeledMetricsValues(MetricsCondition condition,
+                                                        List<String> labels,
+                                                        Duration duration) throws IOException {
+        return getMetricQueryDAO().readLabeledMetricsValues(
+            condition, ValueColumnMetadata.INSTANCE.getValueCName(condition.getName()), labels, duration);
+    }
+
+    /**
+     * Heatmap is bucket based value statistic result.
+     */
+    public HeatMap readHeatMap(MetricsCondition condition, Duration duration) throws IOException {
+        return getMetricQueryDAO().readHeatMap(
+            condition, ValueColumnMetadata.INSTANCE.getValueCName(condition.getName()), duration);
+    }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/PaginationUtils.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/PaginationUtils.java
index fe1c816..125e93a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/PaginationUtils.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/PaginationUtils.java
@@ -18,7 +18,7 @@
 
 package org.apache.skywalking.oap.server.core.query;
 
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
 
 public enum PaginationUtils {
     INSTANCE;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationPoint.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/PointOfTime.java
similarity index 63%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationPoint.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/PointOfTime.java
index 049a9bc..aa39547 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationPoint.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/PointOfTime.java
@@ -18,26 +18,29 @@
 
 package org.apache.skywalking.oap.server.core.query;
 
-public class DurationPoint {
+import lombok.Getter;
+import org.apache.skywalking.oap.server.core.Const;
+
+/**
+ * PointOfTime represents any point of time based on different precisions.
+ */
+@Getter
+public class PointOfTime {
     private long point;
-    private long secondsBetween;
-    private long minutesBetween;
 
-    public DurationPoint(long point, long secondsBetween, long minutesBetween) {
+    public PointOfTime(long point) {
         this.point = point;
-        this.secondsBetween = secondsBetween;
-        this.minutesBetween = minutesBetween;
-    }
-
-    public long getPoint() {
-        return point;
-    }
-
-    public long getSecondsBetween() {
-        return secondsBetween;
     }
 
-    public long getMinutesBetween() {
-        return minutesBetween;
+    /**
+     * @return the row id
+     */
+    public String id(String entityId) {
+        // null means scope = all or unexpected entity.
+        if (entityId == null) {
+            return String.valueOf(point);
+        } else {
+            return point + Const.ID_CONNECTOR + entityId;
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java
index d49d3ba..5f272aa 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java
@@ -32,15 +32,15 @@ import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentReco
 import org.apache.skywalking.oap.server.core.cache.NetworkAddressAliasCache;
 import org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogService;
 import org.apache.skywalking.oap.server.core.profile.analyze.ProfileAnalyzer;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
-import org.apache.skywalking.oap.server.core.query.entity.KeyValue;
-import org.apache.skywalking.oap.server.core.query.entity.LogEntity;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzation;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLog;
-import org.apache.skywalking.oap.server.core.query.entity.ProfiledSegment;
-import org.apache.skywalking.oap.server.core.query.entity.ProfiledSpan;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.KeyValue;
+import org.apache.skywalking.oap.server.core.query.type.LogEntity;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzation;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzeTimeRange;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLog;
+import org.apache.skywalking.oap.server.core.query.type.ProfiledSegment;
+import org.apache.skywalking.oap.server.core.query.type.ProfiledSpan;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceInstanceTopologyBuilder.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceInstanceTopologyBuilder.java
index 0d94ec2..de9418e 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceInstanceTopologyBuilder.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceInstanceTopologyBuilder.java
@@ -27,9 +27,9 @@ import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogService;
-import org.apache.skywalking.oap.server.core.query.entity.Call;
-import org.apache.skywalking.oap.server.core.query.entity.ServiceInstanceNode;
-import org.apache.skywalking.oap.server.core.query.entity.ServiceInstanceTopology;
+import org.apache.skywalking.oap.server.core.query.type.Call;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstanceNode;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstanceTopology;
 import org.apache.skywalking.oap.server.core.source.DetectPoint;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceTopologyBuilder.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceTopologyBuilder.java
index e7352a7..3428d5e 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceTopologyBuilder.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceTopologyBuilder.java
@@ -31,9 +31,9 @@ import org.apache.skywalking.oap.server.core.analysis.NodeType;
 import org.apache.skywalking.oap.server.core.analysis.manual.networkalias.NetworkAddressAlias;
 import org.apache.skywalking.oap.server.core.cache.NetworkAddressAliasCache;
 import org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogService;
-import org.apache.skywalking.oap.server.core.query.entity.Call;
-import org.apache.skywalking.oap.server.core.query.entity.Node;
-import org.apache.skywalking.oap.server.core.query.entity.Topology;
+import org.apache.skywalking.oap.server.core.query.type.Call;
+import org.apache.skywalking.oap.server.core.query.type.Node;
+import org.apache.skywalking.oap.server.core.query.type.Topology;
 import org.apache.skywalking.oap.server.core.source.DetectPoint;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/StepToDownSampling.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/StepToDownSampling.java
deleted file mode 100644
index 149aaae..0000000
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/StepToDownSampling.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.skywalking.oap.server.core.query;
-
-import org.apache.skywalking.oap.server.core.UnexpectedException;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
-import org.apache.skywalking.oap.server.core.query.entity.Step;
-
-public class StepToDownSampling {
-
-    public static DownSampling transform(Step step) {
-        switch (step) {
-            case SECOND:
-                return DownSampling.Second;
-            case MINUTE:
-                return DownSampling.Minute;
-            case HOUR:
-                return DownSampling.Hour;
-            case DAY:
-                return DownSampling.Day;
-        }
-        throw new UnexpectedException("Unknown step value.");
-    }
-}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java
index 21c72e5..1e8e4c8 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java
@@ -20,8 +20,9 @@ package org.apache.skywalking.oap.server.core.query;
 
 import java.io.IOException;
 import java.util.List;
-import org.apache.skywalking.oap.server.core.query.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNRecord;
+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.SelectedRecord;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
@@ -44,8 +45,7 @@ public class TopNRecordsQueryService implements Service {
         return topNRecordsQueryDAO;
     }
 
-    public List<TopNRecord> getTopNRecords(long startSecondTB, long endSecondTB, String metricName, String serviceId,
-        int topN, Order order) throws IOException {
-        return getTopNRecordsQueryDAO().getTopNRecords(startSecondTB, endSecondTB, metricName, serviceId, topN, order);
+    public List<SelectedRecord> readSampledRecords(TopNCondition condition, Duration duration) throws IOException {
+        return getTopNRecordsQueryDAO().readSampledRecords(condition, duration);
     }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopologyQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopologyQueryService.java
index a15474c..4b0ee5b 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopologyQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopologyQueryService.java
@@ -27,13 +27,12 @@ import java.util.Set;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.oap.server.core.Const;
 import org.apache.skywalking.oap.server.core.CoreModule;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogService;
-import org.apache.skywalking.oap.server.core.query.entity.Call;
-import org.apache.skywalking.oap.server.core.query.entity.Node;
-import org.apache.skywalking.oap.server.core.query.entity.ServiceInstanceTopology;
-import org.apache.skywalking.oap.server.core.query.entity.Topology;
+import org.apache.skywalking.oap.server.core.query.type.Call;
+import org.apache.skywalking.oap.server.core.query.type.Node;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstanceTopology;
+import org.apache.skywalking.oap.server.core.query.type.Topology;
 import org.apache.skywalking.oap.server.core.source.DetectPoint;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
@@ -67,24 +66,23 @@ public class TopologyQueryService implements Service {
         return componentLibraryCatalogService;
     }
 
-    public Topology getGlobalTopology(final DownSampling downsampling, final long startTB,
+    public Topology getGlobalTopology(final long startTB,
                                       final long endTB) throws IOException {
-        log.debug("Downsampling: {}, startTimeBucket: {}, endTimeBucket: {}", downsampling, startTB, endTB);
         List<Call.CallDetail> serviceRelationServerCalls = getTopologyQueryDAO().loadServiceRelationsDetectedAtServerSide(
-            downsampling, startTB, endTB);
+            startTB, endTB);
         List<Call.CallDetail> serviceRelationClientCalls = getTopologyQueryDAO().loadServiceRelationDetectedAtClientSide(
-            downsampling, startTB, endTB);
+            startTB, endTB);
 
         ServiceTopologyBuilder builder = new ServiceTopologyBuilder(moduleManager);
         return builder.build(serviceRelationClientCalls, serviceRelationServerCalls);
     }
 
-    public Topology getServiceTopology(final DownSampling downsampling, final long startTB, final long endTB,
+    public Topology getServiceTopology(final long startTB, final long endTB,
                                        final List<String> serviceIds) throws IOException {
         List<Call.CallDetail> serviceRelationClientCalls = getTopologyQueryDAO().loadServiceRelationDetectedAtClientSide(
-            downsampling, startTB, endTB, serviceIds);
+            startTB, endTB, serviceIds);
         List<Call.CallDetail> serviceRelationServerCalls = getTopologyQueryDAO().loadServiceRelationsDetectedAtServerSide(
-            downsampling, startTB, endTB, serviceIds);
+            startTB, endTB, serviceIds);
 
         ServiceTopologyBuilder builder = new ServiceTopologyBuilder(moduleManager);
         Topology topology = builder.build(serviceRelationClientCalls, serviceRelationServerCalls);
@@ -105,7 +103,7 @@ public class TopologyQueryService implements Service {
         if (CollectionUtils.isNotEmpty(outScopeSourceServiceIds)) {
             // If exist, query them as the server side to get the target's component.
             List<Call.CallDetail> sourceCalls = getTopologyQueryDAO().loadServiceRelationsDetectedAtServerSide(
-                downsampling, startTB, endTB, outScopeSourceServiceIds);
+                startTB, endTB, outScopeSourceServiceIds);
             topology.getNodes().forEach(node -> {
                 if (Strings.isNullOrEmpty(node.getType())) {
                     for (Call.CallDetail call : sourceCalls) {
@@ -123,27 +121,21 @@ public class TopologyQueryService implements Service {
 
     public ServiceInstanceTopology getServiceInstanceTopology(final String clientServiceId,
                                                               final String serverServiceId,
-                                                              final DownSampling downsampling,
                                                               final long startTB,
                                                               final long endTB) throws IOException {
-        log.debug(
-            "ClientServiceId: {}, ServerServiceId: {}, Downsampling: {}, startTimeBucket: {}, endTimeBucket: {}",
-            clientServiceId, serverServiceId, downsampling, startTB, endTB
-        );
-
         List<Call.CallDetail> serviceInstanceRelationClientCalls = getTopologyQueryDAO().loadInstanceRelationDetectedAtClientSide(
-            clientServiceId, serverServiceId, downsampling, startTB, endTB);
+            clientServiceId, serverServiceId, startTB, endTB);
         List<Call.CallDetail> serviceInstanceRelationServerCalls = getTopologyQueryDAO().loadInstanceRelationDetectedAtServerSide(
-            clientServiceId, serverServiceId, downsampling, startTB, endTB);
+            clientServiceId, serverServiceId, startTB, endTB);
 
         ServiceInstanceTopologyBuilder builder = new ServiceInstanceTopologyBuilder(moduleManager);
         return builder.build(serviceInstanceRelationClientCalls, serviceInstanceRelationServerCalls);
     }
 
-    public Topology getEndpointTopology(final DownSampling downsampling, final long startTB, final long endTB,
+    public Topology getEndpointTopology(final long startTB, final long endTB,
                                         final String endpointId) throws IOException {
         List<Call.CallDetail> serverSideCalls = getTopologyQueryDAO().loadEndpointRelation(
-            downsampling, startTB, endTB, endpointId);
+            startTB, endTB, endpointId);
 
         Topology topology = new Topology();
         serverSideCalls.forEach(callDetail -> {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TraceQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TraceQueryService.java
index 59c41c0..4fc0c87 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TraceQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TraceQueryService.java
@@ -28,16 +28,16 @@ import org.apache.skywalking.oap.server.core.Const;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
 import org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogService;
-import org.apache.skywalking.oap.server.core.query.entity.KeyValue;
-import org.apache.skywalking.oap.server.core.query.entity.LogEntity;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.Ref;
-import org.apache.skywalking.oap.server.core.query.entity.RefType;
-import org.apache.skywalking.oap.server.core.query.entity.Span;
-import org.apache.skywalking.oap.server.core.query.entity.Trace;
-import org.apache.skywalking.oap.server.core.query.entity.TraceBrief;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.type.KeyValue;
+import org.apache.skywalking.oap.server.core.query.type.LogEntity;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.Ref;
+import org.apache.skywalking.oap.server.core.query.type.RefType;
+import org.apache.skywalking.oap.server.core.query.type.Span;
+import org.apache.skywalking.oap.server.core.query.type.Trace;
+import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Thermodynamic.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Thermodynamic.java
deleted file mode 100644
index 759bb85..0000000
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Thermodynamic.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.skywalking.oap.server.core.query.entity;
-
-import java.util.ArrayList;
-import java.util.List;
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-public class Thermodynamic {
-    private final List<List<Long>> nodes;
-    @Setter
-    private int axisYStep;
-
-    public Thermodynamic() {
-        this.nodes = new ArrayList<>();
-    }
-
-    public void fromMatrixData(List<List<Long>> thermodynamicValueMatrix, int numOfSteps) {
-        thermodynamicValueMatrix.forEach(columnOfThermodynamic -> {
-            if (columnOfThermodynamic.size() == 0) {
-                if (numOfSteps > 0) {
-                    for (int i = 0; i < numOfSteps; i++) {
-                        columnOfThermodynamic.add(0L);
-                    }
-                }
-            }
-        });
-
-        for (int colNum = 0; colNum < thermodynamicValueMatrix.size(); colNum++) {
-            List<Long> column = thermodynamicValueMatrix.get(colNum);
-            for (int rowNum = 0; rowNum < column.size(); rowNum++) {
-                Long value = column.get(rowNum);
-                this.setNodeValue(colNum, rowNum, value);
-            }
-        }
-    }
-
-    private void setNodeValue(int columnNum, int rowNum, Long value) {
-        List<Long> element = new ArrayList<>(3);
-        element.add((long) columnNum);
-        element.add((long) rowNum);
-        element.add(value);
-        nodes.add(element);
-    }
-}
\ No newline at end of file
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/LanguageTrans.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Language.java
similarity index 87%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/LanguageTrans.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Language.java
index 3403179..714797b 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/LanguageTrans.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Language.java
@@ -16,12 +16,12 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.enumeration;
 
-public enum LanguageTrans {
-    INSTANCE;
+public enum Language {
+    UNKNOWN, JAVA, DOTNET, NODEJS, PYTHON, RUBY, GO, LUA, PHP;
 
-    public Language value(String language) {
+    public static Language value(String language) {
         switch (language) {
             case "java":
                 return Language.JAVA;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/type/StorageDataComplexObject.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/MetricsType.java
similarity index 59%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/type/StorageDataComplexObject.java
copy to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/MetricsType.java
index 079c0e1..d4f47ac 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/type/StorageDataComplexObject.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/MetricsType.java
@@ -16,24 +16,20 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.storage.type;
+package org.apache.skywalking.oap.server.core.query.enumeration;
 
 /**
- * StorageDataComplexObject implementation supports String-Object interconversion.
+ * @since 8.0.0
  */
-public interface StorageDataComplexObject {
-    /**
-     * @return string representing this object.
-     */
-    String toStorageData();
-
-    /**
-     * Initialize this object based on the given string data.
-     */
-    void toObject(String data);
-
-    /**
-     * Initialize the object based on the given source.
-     */
-    void copyFrom(Object source);
+public enum MetricsType {
+    UNKNOWN,
+    // Regular value type is suitable for readMetricsValue, readMetricsValues and sortMetrics
+    REGULAR_VALUE,
+    // Metrics value includes multiple labels, is suitable for readLabeledMetricsValues
+    // Label should be assigned before the query happens, such as at the setting stage
+    LABELED_VALUE,
+    // Heatmap value suitable for readHeatMap
+    HEATMAP,
+    // Top metrics is for readSampledRecords only.
+    SAMPLED_RECORD
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Order.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Order.java
similarity index 92%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Order.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Order.java
index 52bd647..61e638a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Order.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Order.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.enumeration;
 
 public enum Order {
     ASC, DES
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Scope.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Scope.java
similarity index 78%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Scope.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Scope.java
index e01006c..97cf41a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Scope.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Scope.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.enumeration;
 
 import java.util.HashMap;
 import lombok.Getter;
@@ -24,7 +24,13 @@ import org.apache.skywalking.oap.server.core.UnexpectedException;
 import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
 
 public enum Scope {
-    Service(DefaultScopeDefine.SERVICE), ServiceInstance(DefaultScopeDefine.SERVICE_INSTANCE), Endpoint(DefaultScopeDefine.ENDPOINT), ServiceRelation(DefaultScopeDefine.SERVICE_RELATION), ServiceInstanceRelation(DefaultScopeDefine.SERVICE_INSTANCE_RELATION), EndpointRelation(DefaultScopeDefine.ENDPOINT_RELATION);
+    All(DefaultScopeDefine.ALL),
+    Service(DefaultScopeDefine.SERVICE),
+    ServiceInstance(DefaultScopeDefine.SERVICE_INSTANCE),
+    Endpoint(DefaultScopeDefine.ENDPOINT),
+    ServiceRelation(DefaultScopeDefine.SERVICE_RELATION),
+    ServiceInstanceRelation(DefaultScopeDefine.SERVICE_INSTANCE_RELATION),
+    EndpointRelation(DefaultScopeDefine.ENDPOINT_RELATION);
 
     @Getter
     private int scopeId;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Step.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Step.java
similarity index 92%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Step.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Step.java
index cd2ac4f..0da5c4c 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Step.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/enumeration/Step.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.enumeration;
 
 public enum Step {
     DAY, HOUR, MINUTE, SECOND
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
new file mode 100644
index 0000000..e58736b
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java
@@ -0,0 +1,69 @@
+/*
+ * 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.skywalking.oap.server.core.query.input;
+
+import java.util.List;
+import lombok.Getter;
+import org.apache.skywalking.oap.server.core.query.DurationUtils;
+import org.apache.skywalking.oap.server.core.query.PointOfTime;
+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);
+    }
+
+    public long getStartTimestamp() {
+        return DurationUtils.INSTANCE.startTimeToTimestamp(step, start);
+    }
+
+    public long getEndTimestamp() {
+        return DurationUtils.INSTANCE.startTimeToTimestamp(step, end);
+    }
+
+    public long getStartTimeBucketInSec() {
+        return DurationUtils.INSTANCE.startTimeDurationToSecondTimeBucket(step, start);
+    }
+
+    public long getEndTimeBucketInSec() {
+        return DurationUtils.INSTANCE.endTimeDurationToSecondTimeBucket(step, end);
+    }
+
+    /**
+     * Assemble time point based on {@link #step} and {@link #start} / {@link #end}
+     */
+    public List<PointOfTime> assembleDurationPoints() {
+        return DurationUtils.INSTANCE.getDurationPoints(step, getStartTimeBucket(), getEndTimeBucket());
+    }
+}
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
new file mode 100644
index 0000000..6e9f732
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Entity.java
@@ -0,0 +1,112 @@
+/*
+ * 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.skywalking.oap.server.core.query.input;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
+
+/**
+ * Entity represents the query entity, including service, instance, endpoint and conjecture service.
+ *
+ * @since 8.0.0
+ */
+@Setter
+@Getter
+public class Entity {
+    /**
+     * <pre>
+     * 1. scope=All, no name is required.
+     * 2. scope=Service, ServiceInstance and Endpoint, set neccessary serviceName/serviceInstanceName/endpointName
+     * 3. Scope=ServiceRelation, ServiceInstanceRelation and EndpointRelation
+     *    serviceName/serviceInstanceName/endpointName is/are the source(s)
+     *    estServiceName/destServiceInstanceName/destEndpointName is/are destination(s)
+     *    set necessary names of sources and destinations.
+     * </pre>
+     */
+    private Scope scope;
+
+    private String serviceName;
+    /**
+     * Normal service is the service having installed agent or metrics reported directly. Unnormal service is
+     * conjectural service, usually detected by the agent.
+     */
+    private boolean isNormal;
+    private String serviceInstanceName;
+    private String endpointName;
+
+    private String destServiceName;
+    /**
+     * Normal service is the service having installed agent or metrics reported directly. Unnormal service is
+     * conjectural service, usually detected by the agent.
+     */
+    private boolean destIsNormal;
+    private String destServiceInstanceName;
+    private String destEndpointName;
+
+    public boolean isService() {
+        return Scope.Service.equals(scope);
+    }
+
+    /**
+     * @return entity id based on the definition.
+     */
+    public String buildId() {
+        switch (scope) {
+            case All:
+                // This is unnecessary. Just for making core clear.
+                return null;
+            case Service:
+                return IDManager.ServiceID.buildId(serviceName, isNormal);
+            case ServiceInstance:
+                return IDManager.ServiceInstanceID.buildId(
+                    IDManager.ServiceID.buildId(serviceName, isNormal), serviceInstanceName);
+            case Endpoint:
+                return IDManager.EndpointID.buildId(IDManager.ServiceID.buildId(serviceName, isNormal), endpointName);
+            case ServiceRelation:
+                return IDManager.ServiceID.buildRelationId(
+                    new IDManager.ServiceID.ServiceRelationDefine(
+                        IDManager.ServiceID.buildId(serviceName, isNormal),
+                        IDManager.ServiceID.buildId(destServiceName, destIsNormal)
+                    )
+                );
+            case ServiceInstanceRelation:
+                return IDManager.ServiceInstanceID.buildRelationId(
+                    new IDManager.ServiceInstanceID.ServiceInstanceRelationDefine(
+                        IDManager.ServiceInstanceID.buildId(
+                            IDManager.ServiceID.buildId(serviceName, isNormal), serviceInstanceName),
+                        IDManager.ServiceInstanceID.buildId(
+                            IDManager.ServiceID.buildId(destServiceName, destIsNormal), destServiceInstanceName)
+                    )
+                );
+            case EndpointRelation:
+                return IDManager.EndpointID.buildRelationId(
+                    new IDManager.EndpointID.EndpointRelationDefine(
+                        IDManager.ServiceID.buildId(serviceName, isNormal),
+                        endpointName,
+                        IDManager.ServiceID.buildId(destServiceName, destIsNormal),
+                        destEndpointName
+                    )
+                );
+            default:
+                return null;
+        }
+    }
+}
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/LogQueryCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/LogQueryCondition.java
similarity index 85%
rename from oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/LogQueryCondition.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/LogQueryCondition.java
index 69ceaa0..4154ef9 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/LogQueryCondition.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/LogQueryCondition.java
@@ -16,12 +16,12 @@
  *
  */
 
-package org.apache.skywalking.oap.query.graphql.type;
+package org.apache.skywalking.oap.server.core.query.input;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.skywalking.oap.server.core.query.entity.LogState;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.LogState;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
 
 @Getter
 @Setter
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/MetricCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/MetricCondition.java
similarity index 94%
rename from oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/MetricCondition.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/MetricCondition.java
index 5762fc7..127618c 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/MetricCondition.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/MetricCondition.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.query.graphql.type;
+package org.apache.skywalking.oap.server.core.query.input;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/MetricsCondition.java
similarity index 80%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java
copy to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/MetricsCondition.java
index 92745b5..11c1232 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/MetricsCondition.java
@@ -16,18 +16,23 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.input;
 
 import lombok.Getter;
 import lombok.Setter;
 
 /**
- *
- **/
+ * @since 8.0.0
+ */
 @Getter
 @Setter
-public class Database {
-    private String id;
+public class MetricsCondition {
+    /**
+     * Metrics name
+     */
     private String name;
-    private String type;
+    /**
+     * See {@link Entity}
+     */
+    private Entity entity;
 }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/ProfileTaskCreationRequest.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/ProfileTaskCreationRequest.java
similarity index 90%
rename from oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/ProfileTaskCreationRequest.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/ProfileTaskCreationRequest.java
index 8da3f8e..3e0d83a 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/ProfileTaskCreationRequest.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/ProfileTaskCreationRequest.java
@@ -16,11 +16,11 @@
  *
  */
 
-package org.apache.skywalking.oap.query.graphql.type;
+package org.apache.skywalking.oap.server.core.query.input;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.skywalking.oap.server.core.query.entity.Step;
+import org.apache.skywalking.oap.server.core.query.enumeration.Step;
 
 /**
  * Profile task create need data
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
new file mode 100644
index 0000000..6964184
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TopNCondition.java
@@ -0,0 +1,55 @@
+/*
+ * 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.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 {
+    /**
+     * Metrics name
+     */
+    private String name;
+    /**
+     * See {@link Entity}
+     */
+    private String parentService;
+    /**
+     * Normal service is the service having installed agent or metrics reported directly. Unnormal service is
+     * conjectural service, usually detected by the agent.
+     */
+    private boolean isNormal;
+    /**
+     * 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-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/TraceQueryCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TraceQueryCondition.java
similarity index 82%
rename from oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/TraceQueryCondition.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TraceQueryCondition.java
index 645e58e..86cfb14 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/TraceQueryCondition.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TraceQueryCondition.java
@@ -16,13 +16,13 @@
  *
  */
 
-package org.apache.skywalking.oap.query.graphql.type;
+package org.apache.skywalking.oap.server.core.query.input;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 
 @Getter
 @Setter
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/AlarmMessage.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/AlarmMessage.java
similarity index 88%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/AlarmMessage.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/AlarmMessage.java
index 044dba4..a8f8b23 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/AlarmMessage.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/AlarmMessage.java
@@ -16,10 +16,11 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
 
 @Getter
 @Setter
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/AlarmTrend.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/AlarmTrend.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/AlarmTrend.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/AlarmTrend.java
index 8028aee..b0c27fd 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/AlarmTrend.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/AlarmTrend.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Alarms.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Alarms.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Alarms.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Alarms.java
index af813f9..bd85d51 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Alarms.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Alarms.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Attribute.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Attribute.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Attribute.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Attribute.java
index a53dd77..b7067ff 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Attribute.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Attribute.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/BasicTrace.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/BasicTrace.java
similarity index 95%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/BasicTrace.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/BasicTrace.java
index 4511c98..eac8f8b 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/BasicTrace.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/BasicTrace.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Bucket.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Bucket.java
new file mode 100644
index 0000000..023ff80
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Bucket.java
@@ -0,0 +1,82 @@
+/*
+ * 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.skywalking.oap.server.core.query.type;
+
+/**
+ * @since 8.0.0
+ */
+public class Bucket {
+    private static final String INFINITE_NEGATIVE = "infinite-";
+    private static final String INFINITE_POSITIVE = "infinite+";
+
+    /**
+     * The min value of this bucket representing.
+     */
+    private String min = "0";
+    /**
+     * The max value of this bucket representing.
+     */
+    private String max = "0";
+
+    public Bucket() {
+    }
+
+    public Bucket(int min, int max) {
+        setMin(min);
+        setMax(max);
+    }
+
+    public Bucket setMin(int min) {
+        this.min = String.valueOf(min);
+        return this;
+    }
+
+    public Bucket setMax(int max) {
+        this.max = String.valueOf(max);
+        return this;
+    }
+
+    public Bucket infiniteMin() {
+        this.min = INFINITE_NEGATIVE;
+        return this;
+    }
+
+    public Bucket infiniteMax() {
+        this.max = INFINITE_POSITIVE;
+        return this;
+    }
+
+    public boolean isInfiniteMin() {
+        return INFINITE_NEGATIVE.equals(this.min);
+    }
+
+    public boolean isInfiniteMax() {
+        return INFINITE_POSITIVE.equals(this.max);
+    }
+
+    public int duration() {
+        if (isInfiniteMin()) {
+            return Integer.MIN_VALUE;
+        }
+        if (isInfiniteMax()) {
+            return Integer.MAX_VALUE;
+        }
+        return Integer.parseInt(this.max) - Integer.parseInt(this.min);
+    }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Call.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Call.java
similarity index 98%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Call.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Call.java
index f6177fb..e7b6ad9 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Call.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Call.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ClusterBrief.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ClusterBrief.java
similarity index 79%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ClusterBrief.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ClusterBrief.java
index ad05b14..a65269e 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ClusterBrief.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ClusterBrief.java
@@ -16,17 +16,18 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
 
+@Deprecated
 @Getter
 @Setter
 public class ClusterBrief {
-    private int numOfService;
-    private int numOfEndpoint;
-    private int numOfDatabase;
-    private int numOfCache;
-    private int numOfMQ;
+    private int numOfService = 0;
+    private int numOfEndpoint = 0;
+    private int numOfDatabase = 0;
+    private int numOfCache = 0;
+    private int numOfMQ = 0;
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ContentType.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ContentType.java
similarity index 95%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ContentType.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ContentType.java
index 49c805d..0fd5ae7 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ContentType.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ContentType.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import org.apache.skywalking.oap.server.core.UnexpectedException;
 
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Database.java
similarity index 94%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java
copy to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Database.java
index 92745b5..48a8dac 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Database.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Endpoint.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Endpoint.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Endpoint.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Endpoint.java
index 73e5cf8..a6e4b4c 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Endpoint.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Endpoint.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/EndpointInfo.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/EndpointInfo.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/EndpointInfo.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/EndpointInfo.java
index b301683..480e90a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/EndpointInfo.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/EndpointInfo.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java
new file mode 100644
index 0000000..2ebff0a
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java
@@ -0,0 +1,113 @@
+/*
+ * 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.skywalking.oap.server.core.query.type;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
+
+/**
+ * HeatMap represents the value distribution in the defined buckets.
+ *
+ * @since 8.0.0
+ */
+@Getter
+public class HeatMap {
+    private List<HeatMapColumn> values = new ArrayList<>(10);
+    private List<Bucket> buckets = null;
+
+    public void addBucket(Bucket bucket) {
+        this.buckets.add(bucket);
+    }
+
+    /**
+     * Build one heatmap value column based on rawdata in the storage and row id.
+     *
+     * @param id      of the row
+     * @param rawdata literal string, represent a {@link DataTable}
+     */
+    public void buildColumn(String id, String rawdata) {
+        DataTable dataset = new DataTable(rawdata);
+
+        final List<String> sortedKeys = dataset.sortedKeys(
+            Comparator.comparingInt(Integer::parseInt));
+        if (buckets == null) {
+            buckets = new ArrayList<>(dataset.size());
+            for (int i = 0; i < sortedKeys.size(); i++) {
+                if (i == sortedKeys.size() - 1) {
+                    // last element
+                    this.addBucket(
+                        new Bucket().setMin(Integer.parseInt(sortedKeys.get(i))).infiniteMax()
+                    );
+                } else {
+                    this.addBucket(new Bucket(
+                        Integer.parseInt(sortedKeys.get(i)),
+                        Integer.parseInt(sortedKeys.get(i + 1))
+                    ));
+                }
+            }
+        }
+
+        HeatMap.HeatMapColumn column = new HeatMap.HeatMapColumn();
+        column.setId(id);
+        sortedKeys.forEach(key -> {
+            column.addValue(dataset.get(key));
+        });
+        values.add(column);
+    }
+
+    public void fixMissingColumns(List<String> ids) {
+        for (int i = 0; i < ids.size(); i++) {
+            final String expectedId = ids.get(i);
+            boolean found = false;
+            for (final HeatMapColumn value : values) {
+                if (expectedId.equals(value.id)) {
+                    found = true;
+                }
+            }
+            if (!found) {
+                final HeatMapColumn emptyColumn = buildMissingColumn(expectedId);
+                values.add(i, emptyColumn);
+            }
+        }
+    }
+
+    private HeatMapColumn buildMissingColumn(String id) {
+        HeatMapColumn column = new HeatMapColumn();
+        column.setId(id);
+        buckets.forEach(bucket -> {
+            column.addValue(0L);
+        });
+        return column;
+    }
+
+    @Getter
+    public static class HeatMapColumn {
+        @Setter
+        private String id;
+        private List<Long> values = new ArrayList<>();
+
+        public void addValue(Long value) {
+            values.add(value);
+        }
+    }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/IntValues.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/IntValues.java
similarity index 73%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/IntValues.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/IntValues.java
index 4ab6c69..53fdf91 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/IntValues.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/IntValues.java
@@ -16,13 +16,13 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
-import java.util.LinkedList;
+import java.util.ArrayList;
+import java.util.List;
 
 public class IntValues {
-
-    private LinkedList<KVInt> values = new LinkedList<>();
+    private List<KVInt> values = new ArrayList<>();
 
     public void addKVInt(KVInt e) {
         values.add(e);
@@ -36,17 +36,4 @@ public class IntValues {
         }
         return defaultValue;
     }
-
-    public KVInt getLast() {
-        return values.getLast();
-    }
-
-    public boolean contain(String id) {
-        for (KVInt value : values) {
-            if (value.getId().equals(id)) {
-                return true;
-            }
-        }
-        return false;
-    }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/KVInt.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KVInt.java
similarity index 93%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/KVInt.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KVInt.java
index c3150aa..6cbe687 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/KVInt.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KVInt.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/KeyValue.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/KeyValue.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
index 5dcbc53..f536424 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/KeyValue.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/KeyValue.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Log.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Log.java
similarity index 95%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Log.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Log.java
index e614c82..0751988 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Log.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Log.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/LogEntity.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/LogEntity.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/LogEntity.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/LogEntity.java
index df56398..9092b07 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/LogEntity.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/LogEntity.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/LogState.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/LogState.java
similarity index 93%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/LogState.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/LogState.java
index 78be0ba..2c34e00 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/LogState.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/LogState.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 public enum LogState {
     ALL, SUCCESS, ERROR
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Logs.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Logs.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Logs.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Logs.java
index 5127a94..47ab3b2 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Logs.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Logs.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/MetricsValues.java
similarity index 82%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java
copy to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/MetricsValues.java
index 92745b5..bdd3df3 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/MetricsValues.java
@@ -16,18 +16,17 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
 
 /**
- *
- **/
+ * @since 8.0.0
+ */
 @Getter
 @Setter
-public class Database {
-    private String id;
-    private String name;
-    private String type;
+public class MetricsValues {
+    private String label;
+    private IntValues values = new IntValues();
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Node.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Node.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Node.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Node.java
index 906a063..3e60238 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Node.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Node.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Pagination.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Pagination.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Pagination.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Pagination.java
index 22f004e..2210122 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Pagination.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Pagination.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileAnalyzation.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileAnalyzation.java
similarity index 95%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileAnalyzation.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileAnalyzation.java
index 4285fea..11bf7b5 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileAnalyzation.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileAnalyzation.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileAnalyzeTimeRange.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileAnalyzeTimeRange.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileAnalyzeTimeRange.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileAnalyzeTimeRange.java
index 81bcfe6..4a2c236 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileAnalyzeTimeRange.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileAnalyzeTimeRange.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileStackElement.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileStackElement.java
similarity index 95%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileStackElement.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileStackElement.java
index 26470ba..6c5085f 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileStackElement.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileStackElement.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileStackTree.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileStackTree.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileStackTree.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileStackTree.java
index 91c11e8..604bce8 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileStackTree.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileStackTree.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTask.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTask.java
similarity index 95%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTask.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTask.java
index 7e27aa0..92e2fca 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTask.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTask.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.List;
 import lombok.AllArgsConstructor;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTaskCreationResult.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTaskCreationResult.java
similarity index 95%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTaskCreationResult.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTaskCreationResult.java
index d4fb580..f8a6a65 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTaskCreationResult.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTaskCreationResult.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.AllArgsConstructor;
 import lombok.Builder;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTaskLog.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTaskLog.java
similarity index 95%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTaskLog.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTaskLog.java
index fb1230d..c1f4d83 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTaskLog.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTaskLog.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.AllArgsConstructor;
 import lombok.Builder;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTaskLogOperationType.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTaskLogOperationType.java
similarity index 96%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTaskLogOperationType.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTaskLogOperationType.java
index 322bdf9..1df9c2c 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileTaskLogOperationType.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfileTaskLogOperationType.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfiledSegment.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfiledSegment.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfiledSegment.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfiledSegment.java
index 271dcdc..08acc5a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfiledSegment.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfiledSegment.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfiledSpan.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfiledSpan.java
similarity index 96%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfiledSpan.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfiledSpan.java
index 58eda80..0bce4e9 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfiledSpan.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProfiledSpan.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/QueryOrder.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/QueryOrder.java
similarity index 93%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/QueryOrder.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/QueryOrder.java
index 5aa1042..14579a8 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/QueryOrder.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/QueryOrder.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 public enum QueryOrder {
     BY_START_TIME, BY_DURATION
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Ref.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Ref.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Ref.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Ref.java
index d2822e2..31880b4 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Ref.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Ref.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/RefType.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/RefType.java
similarity index 93%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/RefType.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/RefType.java
index d47798b..e2b178f 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/RefType.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/RefType.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 public enum RefType {
     CROSS_PROCESS, CROSS_THREAD
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/SelectedRecord.java
similarity index 62%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/SelectedRecord.java
index 92745b5..e85ffe5 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Database.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/SelectedRecord.java
@@ -16,18 +16,31 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
 
 /**
- *
- **/
-@Getter
+ * SelectedRecord is an abtract data element, including id, name, value and a reference id.
+ */
 @Setter
-public class Database {
-    private String id;
+@Getter
+public class SelectedRecord {
+    /**
+     * Literal string name for visualization
+     */
     private String name;
-    private String type;
+    /**
+     * ID represents the owner of this entity.
+     */
+    private String id;
+    /**
+     * Usually an integer value as this is metrics.
+     */
+    private String value;
+    /**
+     * Have value, Only if the record has related trace id. UI should show this as an attached value.
+     */
+    private String refId;
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Service.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Service.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Service.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Service.java
index 43b8fd9..a844cc9 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Service.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Service.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstance.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstance.java
similarity index 90%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstance.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstance.java
index a97ee35..3caa648 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstance.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstance.java
@@ -16,12 +16,13 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
 import lombok.Getter;
 import lombok.Setter;
+import org.apache.skywalking.oap.server.core.query.enumeration.Language;
 
 @Getter
 public class ServiceInstance {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstanceNode.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceNode.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstanceNode.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceNode.java
index 7fd2f1a..891af86 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstanceNode.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceNode.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstanceTopology.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceTopology.java
similarity index 95%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstanceTopology.java
copy to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceTopology.java
index 4de98a2..30070d1 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstanceTopology.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceTopology.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Span.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Span.java
similarity index 96%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Span.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Span.java
index 2775e35..9ce279e 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Span.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Span.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstanceTopology.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Thermodynamic.java
similarity index 64%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstanceTopology.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Thermodynamic.java
index 4de98a2..6fb3d8e 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ServiceInstanceTopology.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Thermodynamic.java
@@ -16,20 +16,32 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
 import lombok.Getter;
+import lombok.Setter;
 
+/**
+ * Replaced by {@link HeatMap}
+ */
+@Deprecated
 @Getter
-public class ServiceInstanceTopology {
-
-    private final List<ServiceInstanceNode> nodes;
-    private final List<Call> calls;
+public class Thermodynamic {
+    private final List<List<Long>> nodes;
+    @Setter
+    private int axisYStep;
 
-    public ServiceInstanceTopology() {
+    public Thermodynamic() {
         this.nodes = new ArrayList<>();
-        this.calls = new ArrayList<>();
     }
-}
+
+    public void addNodeValue(int columnNum, int rowNum, Long value) {
+        List<Long> element = new ArrayList<>(3);
+        element.add((long) columnNum);
+        element.add((long) rowNum);
+        element.add(value);
+        nodes.add(element);
+    }
+}
\ No newline at end of file
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TopNEntity.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNEntity.java
similarity index 73%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TopNEntity.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNEntity.java
index 1f716ab..697c570 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TopNEntity.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNEntity.java
@@ -16,15 +16,28 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+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
 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/query/entity/TopNRecord.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNRecord.java
similarity index 88%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TopNRecord.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNRecord.java
index 3dda16e..27c4625 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TopNRecord.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TopNRecord.java
@@ -16,11 +16,15 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import lombok.Getter;
 import lombok.Setter;
 
+/**
+ * @since 8.0.0 replaced by {@link SelectedRecord}
+ */
+@Deprecated
 @Setter
 @Getter
 public class TopNRecord {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Topology.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Topology.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Topology.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Topology.java
index 4e52fe7..7b57115 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Topology.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Topology.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Trace.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Trace.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Trace.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Trace.java
index 669c5d6..abe1482 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/Trace.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Trace.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TraceBrief.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TraceBrief.java
similarity index 94%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TraceBrief.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TraceBrief.java
index 9e0f1a7..b18ac4d 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TraceBrief.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TraceBrief.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TraceState.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TraceState.java
similarity index 93%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TraceState.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TraceState.java
index 0e36e60..e3f6f63 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/TraceState.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/TraceState.java
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.entity;
+package org.apache.skywalking.oap.server.core.query.type;
 
 public enum TraceState {
     ALL, SUCCESS, ERROR,
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/AbstractLog.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/AbstractLog.java
index 165e2d1..352393a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/AbstractLog.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/AbstractLog.java
@@ -21,7 +21,7 @@ package org.apache.skywalking.oap.server.core.source;
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.skywalking.oap.server.core.UnexpectedException;
-import org.apache.skywalking.oap.server.core.query.entity.ContentType;
+import org.apache.skywalking.oap.server.core.query.type.ContentType;
 
 @Setter
 @Getter
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/Column.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/Column.java
index 8c2f703..6a8ddb5 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/Column.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/Column.java
@@ -48,6 +48,11 @@ public @interface Column {
     Function function() default Function.None;
 
     /**
+     * The default value of this column, when its {@link #isValue()} == true.
+     */
+    int defaultValue() default 0;
+
+    /**
      * Match query means using analyzer(if storage have) to do key word match query.
      */
     boolean matchQuery() default false;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/ValueColumnMetadata.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/ValueColumnMetadata.java
index 174f277..968262f 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/ValueColumnMetadata.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/annotation/ValueColumnMetadata.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.storage.annotation;
 
 import java.util.HashMap;
 import java.util.Map;
+import lombok.RequiredArgsConstructor;
 import org.apache.skywalking.oap.server.core.query.sql.Function;
 
 /**
@@ -34,8 +35,8 @@ public enum ValueColumnMetadata {
     /**
      * Register the new metadata for the given model name.
      */
-    public void putIfAbsent(String modelName, String valueCName, Function function) {
-        mapping.putIfAbsent(modelName, new ValueColumn(valueCName, function));
+    public void putIfAbsent(String modelName, String valueCName, Function function, int defaultValue) {
+        mapping.putIfAbsent(modelName, new ValueColumn(valueCName, function, defaultValue));
     }
 
     /**
@@ -52,6 +53,10 @@ public enum ValueColumnMetadata {
         return findColumn(metricsName).function;
     }
 
+    public int getDefaultValue(String metricsName) {
+        return findColumn(metricsName).defaultValue;
+    }
+
     private ValueColumn findColumn(String metricsName) {
         ValueColumn column = mapping.get(metricsName);
         if (column == null) {
@@ -60,13 +65,10 @@ public enum ValueColumnMetadata {
         return column;
     }
 
+    @RequiredArgsConstructor
     class ValueColumn {
         private final String valueCName;
         private final Function function;
-
-        private ValueColumn(String valueCName, Function function) {
-            this.valueCName = valueCName;
-            this.function = function;
-        }
+        private final int defaultValue;
     }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumn.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumn.java
index 890c9b0..7f8c9a0 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumn.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumn.java
@@ -20,7 +20,7 @@ package org.apache.skywalking.oap.server.core.storage.model;
 
 import com.google.gson.JsonObject;
 import lombok.Getter;
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValueHashMap;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 
 @Getter
 public class ModelColumn {
@@ -51,7 +51,7 @@ public class ModelColumn {
         /*
          * byte[] and {@link IntKeyLongValueHashMap} could never be query.
          */
-        if (type.equals(byte[].class) || type.equals(IntKeyLongValueHashMap.class)) {
+        if (type.equals(byte[].class) || type.equals(DataTable.class)) {
             this.storageOnly = true;
         } else {
             if (storageOnly && isValue) {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java
index d2c08cd..0a25e74 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java
@@ -81,7 +81,8 @@ public class StorageModels implements IModelManager, INewModel, IModelOverride {
                     log.debug("The field named {} with the {} type", column.columnName(), field.getType());
                 }
                 if (column.isValue()) {
-                    ValueColumnMetadata.INSTANCE.putIfAbsent(modelName, column.columnName(), column.function());
+                    ValueColumnMetadata.INSTANCE.putIfAbsent(
+                        modelName, column.columnName(), column.function(), column.defaultValue());
                 }
 
                 List<QueryUnifiedIndex> indexDefinitions = new ArrayList<>();
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileTaskLogQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileTaskLogQueryDAO.java
index d33dd46..582755c 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileTaskLogQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileTaskLogQueryDAO.java
@@ -20,7 +20,7 @@ package org.apache.skywalking.oap.server.core.storage.profile;
 
 import java.io.IOException;
 import java.util.List;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLog;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLog;
 import org.apache.skywalking.oap.server.core.storage.DAO;
 
 /**
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileTaskQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileTaskQueryDAO.java
index 8acd250..32a9c3a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileTaskQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileTaskQueryDAO.java
@@ -20,7 +20,7 @@ package org.apache.skywalking.oap.server.core.storage.profile;
 
 import java.io.IOException;
 import java.util.List;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
 import org.apache.skywalking.oap.server.core.storage.DAO;
 
 /**
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileThreadSnapshotQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileThreadSnapshotQueryDAO.java
index 907a418..eb361e1 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileThreadSnapshotQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileThreadSnapshotQueryDAO.java
@@ -23,7 +23,7 @@ import java.util.List;
 
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.storage.DAO;
 
 /**
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 7cd0b5b..5f31903 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.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.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 condition,
+                                     String valueColumnName,
+                                     Duration duration,
+                                     List<KeyValue> additionalConditions) throws IOException;
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IAlarmQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IAlarmQueryDAO.java
index 9317ebf..3278e1d 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IAlarmQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IAlarmQueryDAO.java
@@ -19,7 +19,7 @@
 package org.apache.skywalking.oap.server.core.storage.query;
 
 import java.io.IOException;
-import org.apache.skywalking.oap.server.core.query.entity.Alarms;
+import org.apache.skywalking.oap.server.core.query.type.Alarms;
 import org.apache.skywalking.oap.server.core.storage.DAO;
 
 public interface IAlarmQueryDAO extends DAO {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ILogQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ILogQueryDAO.java
index 69b5e6f..1603fa3 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ILogQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ILogQueryDAO.java
@@ -19,9 +19,9 @@
 package org.apache.skywalking.oap.server.core.storage.query;
 
 import java.io.IOException;
-import org.apache.skywalking.oap.server.core.query.entity.LogState;
-import org.apache.skywalking.oap.server.core.query.entity.Logs;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.LogState;
+import org.apache.skywalking.oap.server.core.query.type.Logs;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
 import org.apache.skywalking.oap.server.library.module.Service;
 
 public interface ILogQueryDAO extends Service {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetadataQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetadataQueryDAO.java
index 55ed3d0..9140031 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetadataQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetadataQueryDAO.java
@@ -20,20 +20,13 @@ package org.apache.skywalking.oap.server.core.storage.query;
 
 import java.io.IOException;
 import java.util.List;
-import org.apache.skywalking.oap.server.core.query.entity.Database;
-import org.apache.skywalking.oap.server.core.query.entity.Endpoint;
-import org.apache.skywalking.oap.server.core.query.entity.Service;
-import org.apache.skywalking.oap.server.core.query.entity.ServiceInstance;
+import org.apache.skywalking.oap.server.core.query.type.Database;
+import org.apache.skywalking.oap.server.core.query.type.Endpoint;
+import org.apache.skywalking.oap.server.core.query.type.Service;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstance;
 import org.apache.skywalking.oap.server.core.storage.DAO;
 
 public interface IMetadataQueryDAO extends DAO {
-
-    int numOfService(final long startTimestamp, final long endTimestamp) throws IOException;
-
-    int numOfEndpoint() throws IOException;
-
-    int numOfConjectural(final int nodeTypeValue) throws IOException;
-
     List<Service> getAllServices(final long startTimestamp, final long endTimestamp) throws IOException;
 
     List<Service> getAllBrowserServices(long startTimestamp, long endTimestamp) throws IOException;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetricsQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetricsQueryDAO.java
index aed908f..79be899 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetricsQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetricsQueryDAO.java
@@ -20,24 +20,61 @@ 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.entity.IntValues;
-import org.apache.skywalking.oap.server.core.query.entity.Thermodynamic;
-import org.apache.skywalking.oap.server.core.query.sql.Function;
-import org.apache.skywalking.oap.server.core.query.sql.Where;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.MetricsCondition;
+import org.apache.skywalking.oap.server.core.query.type.HeatMap;
+import org.apache.skywalking.oap.server.core.query.type.IntValues;
+import org.apache.skywalking.oap.server.core.query.type.KVInt;
+import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
 import org.apache.skywalking.oap.server.core.storage.DAO;
 
+/**
+ * Query metrics values in different ways.
+ *
+ * @since 8.0.0
+ */
 public interface IMetricsQueryDAO extends DAO {
+    int readMetricsValue(MetricsCondition condition, String valueColumnName, Duration duration) throws IOException;
+
+    MetricsValues readMetricsValues(MetricsCondition condition,
+                                    String valueColumnName,
+                                    Duration duration) throws IOException;
+
+    List<MetricsValues> readLabeledMetricsValues(MetricsCondition condition,
+                                                 String valueColumnName,
+                                                 List<String> labels,
+                                                 Duration duration) throws IOException;
+
+    HeatMap readHeatMap(MetricsCondition condition, String valueColumnName, Duration duration) throws IOException;
 
-    IntValues getValues(String indName, DownSampling downsampling, long startTB, long endTB, Where where,
-                        String valueCName, Function function) throws IOException;
+    class Util {
+        /**
+         * Make sure the order is same as the expected order, add defaultValue if absent.
+         */
+        public static IntValues sortValues(IntValues origin, List<String> expectedOrder, int defaultValue) {
+            IntValues intValues = new IntValues();
 
-    IntValues getLinearIntValues(String indName, DownSampling downsampling, List<String> ids,
-                                 String valueCName) throws IOException;
+            expectedOrder.forEach(id -> {
+                KVInt e = new KVInt();
+                e.setId(id);
+                e.setValue(origin.findValue(id, defaultValue));
+                intValues.addKVInt(e);
+            });
 
-    IntValues[] getMultipleLinearIntValues(String indName, DownSampling downsampling, List<String> ids,
-                                           List<Integer> linearIndex, String valueCName) throws IOException;
+            return intValues;
+        }
 
-    Thermodynamic getThermodynamic(String indName, DownSampling downsampling, List<String> ids,
-                                   String valueCName) throws IOException;
+        /**
+         * Make sure the order is same as the expected order, add defaultValue if absent.
+         */
+        public static List<MetricsValues> sortValues(List<MetricsValues> origin,
+                                                     List<String> expectedOrder,
+                                                     int defaultValue) {
+            for (int i = 0; i < origin.size(); i++) {
+                final MetricsValues metricsValues = origin.get(i);
+                metricsValues.setValues(sortValues(metricsValues.getValues(), expectedOrder, defaultValue));
+            }
+            return origin;
+        }
+    }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopNRecordsQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopNRecordsQueryDAO.java
index daf89c9..a818d5c 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopNRecordsQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopNRecordsQueryDAO.java
@@ -20,11 +20,18 @@ package org.apache.skywalking.oap.server.core.storage.query;
 
 import java.io.IOException;
 import java.util.List;
-import org.apache.skywalking.oap.server.core.query.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNRecord;
+import org.apache.skywalking.oap.server.core.analysis.Stream;
+import org.apache.skywalking.oap.server.core.analysis.worker.TopNStreamProcessor;
+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.SelectedRecord;
 import org.apache.skywalking.oap.server.library.module.Service;
 
+/**
+ * Query the records sampled by {@link Stream} = {@link TopNStreamProcessor}
+ *
+ * @since 8.0.0
+ */
 public interface ITopNRecordsQueryDAO extends Service {
-    List<TopNRecord> getTopNRecords(long startSecondTB, long endSecondTB, String metricName, String serviceId, int topN,
-        Order order) throws IOException;
+    List<SelectedRecord> readSampledRecords(TopNCondition condition, Duration duration) throws IOException;
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopologyQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopologyQueryDAO.java
index f1b8c7f..c54a28b 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopologyQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopologyQueryDAO.java
@@ -20,37 +20,36 @@ 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.analysis.manual.relation.instance.ServiceInstanceRelationClientSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.instance.ServiceInstanceRelationServerSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.service.ServiceRelationClientSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.service.ServiceRelationServerSideMetrics;
-import org.apache.skywalking.oap.server.core.query.entity.Call;
+import org.apache.skywalking.oap.server.core.query.type.Call;
 import org.apache.skywalking.oap.server.library.module.Service;
 
 public interface ITopologyQueryDAO extends Service {
     /**
      * Query {@link ServiceRelationServerSideMetrics} through the given conditions
      */
-    List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(DownSampling downsampling, long startTB, long endTB,
+    List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(long startTB, long endTB,
                                                                    List<String> serviceIds) throws IOException;
 
     /**
      * Query {@link ServiceRelationClientSideMetrics} through the given conditions
      */
-    List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(DownSampling downsampling, long startTB, long endTB,
+    List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(long startTB, long endTB,
                                                                   List<String> serviceIds) throws IOException;
 
     /**
      * Query {@link ServiceRelationServerSideMetrics} globally, without given serviceIds
      */
-    List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(DownSampling downsampling, long startTB,
+    List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(long startTB,
                                                                    long endTB) throws IOException;
 
     /**
      * Query {@link ServiceRelationClientSideMetrics} globally, without given serviceIds
      */
-    List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(DownSampling downsampling, long startTB,
+    List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(long startTB,
                                                                   long endTB) throws IOException;
 
     /**
@@ -59,7 +58,6 @@ public interface ITopologyQueryDAO extends Service {
      */
     List<Call.CallDetail> loadInstanceRelationDetectedAtServerSide(String clientServiceId,
                                                                    String serverServiceId,
-                                                                   DownSampling downsampling,
                                                                    long startTB,
                                                                    long endTB) throws IOException;
 
@@ -69,15 +67,13 @@ public interface ITopologyQueryDAO extends Service {
      */
     List<Call.CallDetail> loadInstanceRelationDetectedAtClientSide(String clientServiceId,
                                                                    String serverServiceId,
-                                                                   DownSampling downsampling,
                                                                    long startTB,
                                                                    long endTB) throws IOException;
 
     /**
      * Query the endpoint relationship. Endpoint dependency is not detected from server side agent.
      */
-    List<Call.CallDetail> loadEndpointRelation(DownSampling downsampling,
-                                               long startTB,
+    List<Call.CallDetail> loadEndpointRelation(long startTB,
                                                long endTB,
                                                String destEndpointId) throws IOException;
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITraceQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITraceQueryDAO.java
index 942595b..3660034 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITraceQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITraceQueryDAO.java
@@ -21,10 +21,10 @@ 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.manual.segment.SegmentRecord;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.Span;
-import org.apache.skywalking.oap.server.core.query.entity.TraceBrief;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.Span;
+import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.library.module.Service;
 
 public interface ITraceQueryDAO extends Service {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/type/StorageDataComplexObject.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/type/StorageDataComplexObject.java
index 079c0e1..ebad19e 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/type/StorageDataComplexObject.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/type/StorageDataComplexObject.java
@@ -21,7 +21,7 @@ package org.apache.skywalking.oap.server.core.storage.type;
 /**
  * StorageDataComplexObject implementation supports String-Object interconversion.
  */
-public interface StorageDataComplexObject {
+public interface StorageDataComplexObject<T> {
     /**
      * @return string representing this object.
      */
@@ -35,5 +35,5 @@ public interface StorageDataComplexObject {
     /**
      * Initialize the object based on the given source.
      */
-    void copyFrom(Object source);
+    void copyFrom(T source);
 }
diff --git a/oap-server/server-core/src/main/proto/RemoteService.proto b/oap-server/server-core/src/main/proto/RemoteService.proto
index 48b9ca3..3735526 100644
--- a/oap-server/server-core/src/main/proto/RemoteService.proto
+++ b/oap-server/server-core/src/main/proto/RemoteService.proto
@@ -36,16 +36,7 @@ message RemoteData {
     repeated int64 dataLongs = 2;
     repeated double dataDoubles = 3;
     repeated int32 dataIntegers = 4;
-    repeated DataIntLongPairList dataLists = 5;
-}
-
-message DataIntLongPairList {
-    repeated IntKeyLongValuePair value = 1;
-}
-
-message IntKeyLongValuePair {
-    int32 key = 1;
-    int64 value = 2;
+    repeated string dataTableStrings = 5;
 }
 
 message Empty {
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/DataTableTestCase.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/DataTableTestCase.java
new file mode 100644
index 0000000..08b80af
--- /dev/null
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/DataTableTestCase.java
@@ -0,0 +1,62 @@
+/*
+ * 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.skywalking.oap.server.core.analysis.metrics;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DataTableTestCase {
+
+    private DataTable dataTable;
+
+    @Before
+    public void init() {
+        dataTable = new DataTable();
+        dataTable.put("5", 500L);
+        dataTable.put("6", 600L);
+        dataTable.put("1", 100L);
+        dataTable.put("2", 200L);
+        dataTable.put("7", 700L);
+    }
+
+    @Test
+    public void toStorageData() {
+        Assert.assertEquals("1,100|2,200|5,500|6,600|7,700", dataTable.toStorageData());
+    }
+
+    @Test
+    public void toObject() {
+        DataTable dataTable = new DataTable();
+        dataTable.toObject("1,100|2,200|5,500|6,600|7,700");
+
+        Assert.assertEquals(100, dataTable.get("1").intValue());
+        Assert.assertEquals(200, dataTable.get("2").intValue());
+        Assert.assertEquals(500, dataTable.get("5").intValue());
+        Assert.assertEquals(600, dataTable.get("6").intValue());
+        Assert.assertEquals(700, dataTable.get("7").intValue());
+    }
+
+    @Test
+    public void copyFrom() {
+        DataTable dataTable = new DataTable();
+        dataTable.append(this.dataTable);
+
+        Assert.assertEquals("1,100|2,200|5,500|6,600|7,700", dataTable.toStorageData());
+    }
+}
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/ThermodynamicMetricsTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/HeatMapMetricsTest.java
similarity index 74%
rename from oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/ThermodynamicMetricsTest.java
rename to oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/HeatMapMetricsTest.java
index b9aa988..6be4f77 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/ThermodynamicMetricsTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/HeatMapMetricsTest.java
@@ -18,18 +18,17 @@
 
 package org.apache.skywalking.oap.server.core.analysis.metrics;
 
-import java.util.Map;
 import org.apache.skywalking.oap.server.core.remote.grpc.proto.RemoteData;
 import org.junit.Assert;
 import org.junit.Test;
 
-public class ThermodynamicMetricsTest {
+public class HeatMapMetricsTest {
     private int step = 10; //ms
     private int maxNumOfSteps = 10; //count
 
     @Test
     public void testEntrance() {
-        ThermodynamicMetricsMocker metricsMocker = new ThermodynamicMetricsMocker();
+        HistogramMetricsMocker metricsMocker = new HistogramMetricsMocker();
 
         metricsMocker.combine(2000, step, maxNumOfSteps);
         metricsMocker.combine(110, step, maxNumOfSteps);
@@ -45,18 +44,18 @@ public class ThermodynamicMetricsTest {
         metricsMocker.combine(100, step, maxNumOfSteps);
         metricsMocker.combine(100, step, maxNumOfSteps);
 
-        Map<Integer, IntKeyLongValue> index = metricsMocker.getDetailGroup();
-        Assert.assertEquals(4, index.size());
+        final DataTable dataset = metricsMocker.getDataset();
+        Assert.assertEquals(11, dataset.size());
 
-        Assert.assertEquals(1, index.get(2).getValue());
-        Assert.assertEquals(3, index.get(5).getValue());
-        Assert.assertEquals(1, index.get(6).getValue());
-        Assert.assertEquals(8, index.get(10).getValue());
+        Assert.assertEquals(1, dataset.get("20").intValue());
+        Assert.assertEquals(3, dataset.get("50").intValue());
+        Assert.assertEquals(1, dataset.get("60").intValue());
+        Assert.assertEquals(8, dataset.get("100").intValue());
     }
 
     @Test
     public void testMerge() {
-        ThermodynamicMetricsMocker metricsMocker = new ThermodynamicMetricsMocker();
+        HistogramMetricsMocker metricsMocker = new HistogramMetricsMocker();
 
         metricsMocker.combine(2000, step, maxNumOfSteps);
         metricsMocker.combine(110, step, maxNumOfSteps);
@@ -66,7 +65,7 @@ public class ThermodynamicMetricsTest {
         metricsMocker.combine(50, step, maxNumOfSteps);
         metricsMocker.combine(50, step, maxNumOfSteps);
 
-        ThermodynamicMetricsMocker metricsMocker1 = new ThermodynamicMetricsMocker();
+        HistogramMetricsMocker metricsMocker1 = new HistogramMetricsMocker();
 
         metricsMocker1.combine(28, step, maxNumOfSteps);
         metricsMocker1.combine(50, step, maxNumOfSteps);
@@ -77,16 +76,16 @@ public class ThermodynamicMetricsTest {
 
         metricsMocker.combine(metricsMocker1);
 
-        Map<Integer, IntKeyLongValue> index = metricsMocker.getDetailGroup();
-        Assert.assertEquals(4, index.size());
+        final DataTable dataset = metricsMocker.getDataset();
+        Assert.assertEquals(11, dataset.size());
 
-        Assert.assertEquals(1, index.get(2).getValue());
-        Assert.assertEquals(3, index.get(5).getValue());
-        Assert.assertEquals(1, index.get(6).getValue());
-        Assert.assertEquals(8, index.get(10).getValue());
+        Assert.assertEquals(1, dataset.get("20").intValue());
+        Assert.assertEquals(3, dataset.get("50").intValue());
+        Assert.assertEquals(1, dataset.get("60").intValue());
+        Assert.assertEquals(8, dataset.get("100").intValue());
     }
 
-    public class ThermodynamicMetricsMocker extends ThermodynamicMetrics {
+    public class HistogramMetricsMocker extends HistogramMetrics {
 
         @Override
         public String id() {
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/IntKeyLongValueHashMapTestCase.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/IntKeyLongValueHashMapTestCase.java
deleted file mode 100644
index 8d8a7da..0000000
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/IntKeyLongValueHashMapTestCase.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.skywalking.oap.server.core.analysis.metrics;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-public class IntKeyLongValueHashMapTestCase {
-
-    private IntKeyLongValueHashMap intKeyLongValueHashMap;
-
-    @Before
-    public void init() {
-        IntKeyLongValue v1 = new IntKeyLongValue(5, 500);
-        IntKeyLongValue v2 = new IntKeyLongValue(6, 600);
-        IntKeyLongValue v3 = new IntKeyLongValue(1, 100);
-        IntKeyLongValue v4 = new IntKeyLongValue(2, 200);
-        IntKeyLongValue v5 = new IntKeyLongValue(7, 700);
-
-        intKeyLongValueHashMap = new IntKeyLongValueHashMap();
-        intKeyLongValueHashMap.put(v1.getKey(), v1);
-        intKeyLongValueHashMap.put(v2.getKey(), v2);
-        intKeyLongValueHashMap.put(v3.getKey(), v3);
-        intKeyLongValueHashMap.put(v4.getKey(), v4);
-        intKeyLongValueHashMap.put(v5.getKey(), v5);
-    }
-
-    @Test
-    public void toStorageData() {
-        Assert.assertEquals("1,100|2,200|5,500|6,600|7,700", intKeyLongValueHashMap.toStorageData());
-    }
-
-    @Test
-    public void toObject() {
-        IntKeyLongValueHashMap intKeyLongValueHashMap = new IntKeyLongValueHashMap();
-        intKeyLongValueHashMap.toObject("1,100|2,200|5,500|6,600|7,700");
-
-        Assert.assertEquals(100, intKeyLongValueHashMap.get(1).getValue());
-        Assert.assertEquals(200, intKeyLongValueHashMap.get(2).getValue());
-        Assert.assertEquals(500, intKeyLongValueHashMap.get(5).getValue());
-        Assert.assertEquals(600, intKeyLongValueHashMap.get(6).getValue());
-        Assert.assertEquals(700, intKeyLongValueHashMap.get(7).getValue());
-    }
-
-    @Test
-    public void copyFrom() {
-        IntKeyLongValueHashMap intKeyLongValueHashMap = new IntKeyLongValueHashMap();
-        intKeyLongValueHashMap.copyFrom(this.intKeyLongValueHashMap);
-
-        Assert.assertEquals("1,100|2,200|5,500|6,600|7,700", intKeyLongValueHashMap.toStorageData());
-    }
-}
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/PxxMetricsTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/PxxMetricsTest.java
index dc16629..acbadc1 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/PxxMetricsTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/metrics/PxxMetricsTest.java
@@ -129,7 +129,7 @@ public class PxxMetricsTest {
 
     @Test
     public void testAccurate() {
-        IntKeyLongValueHashMap map = new IntKeyLongValueHashMap();
+        DataTable map = new DataTable();
         map.toObject("0,109|128,3|130,1|131,1|132,2|5,16|6,23|10,1|12,1|13,25|14,10|15,2|17,1|146,2|18,1|19,16|20,9|21,4|22,1|23,2|152,1|25,4|26,4|27,3|28,1|31,1|32,2|34,1|44,1|318,1|319,7|320,2|321,1|323,1|324,1|325,2|326,1|327,3|328,1|330,2|205,27|206,14|208,1|337,1|219,15|220,2|221,2|222,1|224,1|352,1|225,1|226,3|227,1|229,1|232,2|105,16|233,1|106,13|108,1|113,20|114,4|115,3|116,2|118,6|119,12|120,4|121,4|122,6|250,1|124,4|125,1|126,4|127,2");
 
         PxxMetricsMocker metrics50Mocker = new PxxMetricsMocker(50);
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackAnalyze.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackAnalyze.java
index 5c97449..19f9f34 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackAnalyze.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackAnalyze.java
@@ -25,9 +25,9 @@ import java.util.stream.Collectors;
 import lombok.Data;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileStackTree;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzeTimeRange;
+import org.apache.skywalking.oap.server.core.query.type.ProfileStackTree;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 
 import static org.junit.Assert.assertEquals;
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackData.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackData.java
index fc92ec4..c7180f5 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackData.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackData.java
@@ -22,7 +22,7 @@ import com.google.common.base.Splitter;
 import lombok.Data;
 import org.apache.skywalking.apm.network.language.profile.v3.ThreadStack;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzeTimeRange;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackElementMatcher.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackElementMatcher.java
index 696037f..60d371f 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackElementMatcher.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackElementMatcher.java
@@ -25,8 +25,8 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import lombok.Data;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileStackElement;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileStackTree;
+import org.apache.skywalking.oap.server.core.query.type.ProfileStackElement;
+import org.apache.skywalking.oap.server.core.query.type.ProfileStackTree;
 import org.apache.skywalking.oap.server.library.util.CollectionUtils;
 import org.junit.Assert;
 
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumnTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumnTest.java
index e28100c..7c2d0a2 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumnTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumnTest.java
@@ -18,7 +18,7 @@
 
 package org.apache.skywalking.oap.server.core.storage.model;
 
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValueHashMap;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -31,7 +31,7 @@ public class ModelColumnTest {
         Assert.assertEquals(true, column.isStorageOnly());
         Assert.assertEquals("abc", column.getColumnName().getName());
 
-        column = new ModelColumn(new ColumnName("", "abc"), IntKeyLongValueHashMap.class, true,
+        column = new ModelColumn(new ColumnName("", "abc"), DataTable.class, true,
                                  false, true, 200
         );
         Assert.assertEquals(true, column.isStorageOnly());
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java
index 51f0ad3..ddcf103 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java
@@ -26,6 +26,7 @@ import org.apache.skywalking.oap.query.graphql.resolver.AlarmQuery;
 import org.apache.skywalking.oap.query.graphql.resolver.LogQuery;
 import org.apache.skywalking.oap.query.graphql.resolver.MetadataQuery;
 import org.apache.skywalking.oap.query.graphql.resolver.MetricQuery;
+import org.apache.skywalking.oap.query.graphql.resolver.MetricsQuery;
 import org.apache.skywalking.oap.query.graphql.resolver.Mutation;
 import org.apache.skywalking.oap.query.graphql.resolver.ProfileMutation;
 import org.apache.skywalking.oap.query.graphql.resolver.ProfileQuery;
@@ -73,18 +74,28 @@ public class GraphQLQueryProvider extends ModuleProvider {
                                            .resolvers(new Query(), new Mutation())
                                            .file("query-protocol/metadata.graphqls")
                                            .resolvers(new MetadataQuery(getManager()))
-                                           .file("query-protocol/metric.graphqls")
-                                           .resolvers(new MetricQuery(getManager()))
                                            .file("query-protocol/topology.graphqls")
                                            .resolvers(new TopologyQuery(getManager()))
-                                           .file("query-protocol/trace.graphqls")
-                                           .resolvers(new TraceQuery(getManager()))
+                                           /**
+                                            * Metrics v2 query protocol is an alternative metrics query(s) of original v1,
+                                            * defined in the metric.graphql, top-n-records.graphqls, and aggregation.graphqls.
+                                            */
+                                           .file("query-protocol/metrics-v2.graphqls")
+                                           .resolvers(new MetricsQuery(getManager()))
+                                           ////////
+                                           //Deprecated Queries
+                                           ////////
+                                           .file("query-protocol/metric.graphqls")
+                                           .resolvers(new MetricQuery(getManager()))
                                            .file("query-protocol/aggregation.graphqls")
                                            .resolvers(new AggregationQuery(getManager()))
-                                           .file("query-protocol/alarm.graphqls")
-                                           .resolvers(new AlarmQuery(getManager()))
                                            .file("query-protocol/top-n-records.graphqls")
                                            .resolvers(new TopNRecordsQuery(getManager()))
+                                           ////////
+                                           .file("query-protocol/trace.graphqls")
+                                           .resolvers(new TraceQuery(getManager()))
+                                           .file("query-protocol/alarm.graphqls")
+                                           .resolvers(new AlarmQuery(getManager()))
                                            .file("query-protocol/log.graphqls")
                                            .resolvers(new LogQuery(getManager()))
                                            .file("query-protocol/profile.graphqls")
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 6f8a603..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,71 +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.query.graphql.type.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.query.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNEntity;
+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}, 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/AlarmQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AlarmQuery.java
index ed7e3ca..fe38bb9 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AlarmQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AlarmQuery.java
@@ -20,14 +20,13 @@ package org.apache.skywalking.oap.query.graphql.resolver;
 
 import com.coxautodev.graphql.tools.GraphQLQueryResolver;
 import java.io.IOException;
-import org.apache.skywalking.oap.query.graphql.type.Duration;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
-import org.apache.skywalking.oap.server.core.query.DurationUtils;
-import org.apache.skywalking.oap.server.core.query.entity.AlarmTrend;
-import org.apache.skywalking.oap.server.core.query.entity.Alarms;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
-import org.apache.skywalking.oap.server.core.query.entity.Scope;
+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.type.AlarmTrend;
+import org.apache.skywalking.oap.server.core.query.type.Alarms;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
 public class AlarmQuery implements GraphQLQueryResolver {
@@ -51,15 +50,13 @@ public class AlarmQuery implements GraphQLQueryResolver {
     }
 
     public Alarms getAlarm(final Duration duration, final Scope scope, final String keyword,
-        final Pagination paging) throws IOException {
-        long startTimeBucket = DurationUtils.INSTANCE.startTimeDurationToSecondTimeBucket(duration.getStep(), duration.getStart());
-        long endTimeBucket = DurationUtils.INSTANCE.endTimeDurationToSecondTimeBucket(duration.getStep(), duration.getEnd());
-
+                           final Pagination paging) throws IOException {
         Integer scopeId = null;
         if (scope != null) {
             scopeId = scope.getScopeId();
         }
 
-        return getQueryService().getAlarm(scopeId, keyword, paging, startTimeBucket, endTimeBucket);
+        return getQueryService().getAlarm(
+            scopeId, keyword, paging, duration.getStartTimeBucket(), duration.getEndTimeBucket());
     }
 }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/LogQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/LogQuery.java
index b52efc0..156cb0c 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/LogQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/LogQuery.java
@@ -20,11 +20,10 @@ package org.apache.skywalking.oap.query.graphql.resolver;
 
 import com.coxautodev.graphql.tools.GraphQLQueryResolver;
 import java.io.IOException;
-import org.apache.skywalking.oap.query.graphql.type.LogQueryCondition;
 import org.apache.skywalking.oap.server.core.CoreModule;
-import org.apache.skywalking.oap.server.core.query.DurationUtils;
 import org.apache.skywalking.oap.server.core.query.LogQueryService;
-import org.apache.skywalking.oap.server.core.query.entity.Logs;
+import org.apache.skywalking.oap.server.core.query.input.LogQueryCondition;
+import org.apache.skywalking.oap.server.core.query.type.Logs;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
 import static java.util.Objects.nonNull;
@@ -48,15 +47,14 @@ public class LogQuery implements GraphQLQueryResolver {
         long startSecondTB = 0;
         long endSecondTB = 0;
         if (nonNull(condition.getQueryDuration())) {
-            startSecondTB = DurationUtils.INSTANCE.startTimeDurationToSecondTimeBucket(condition.getQueryDuration()
-                                                                                                .getStep(), condition.getQueryDuration()
-                                                                                                                     .getStart());
-            endSecondTB = DurationUtils.INSTANCE.endTimeDurationToSecondTimeBucket(condition.getQueryDuration()
-                                                                                            .getStep(), condition.getQueryDuration()
-                                                                                                                 .getEnd());
+            startSecondTB = condition.getQueryDuration().getStartTimeBucketInSec();
+            endSecondTB = condition.getQueryDuration().getEndTimeBucketInSec();
         }
 
-        return getQueryService().queryLogs(condition.getMetricName(), condition.getServiceId(), condition.getServiceInstanceId(), condition
-            .getEndpointId(), condition.getTraceId(), condition.getState(), condition.getStateCode(), condition.getPaging(), startSecondTB, endSecondTB);
+        return getQueryService().queryLogs(
+            condition.getMetricName(), condition.getServiceId(), condition.getServiceInstanceId(), condition
+                .getEndpointId(), condition.getTraceId(), condition.getState(), condition.getStateCode(),
+            condition.getPaging(), startSecondTB, endSecondTB
+        );
     }
 }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetadataQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetadataQuery.java
index 2c90423..e76caba 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetadataQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetadataQuery.java
@@ -24,17 +24,16 @@ import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
-import org.apache.skywalking.oap.query.graphql.type.Duration;
 import org.apache.skywalking.oap.query.graphql.type.TimeInfo;
 import org.apache.skywalking.oap.server.core.CoreModule;
-import org.apache.skywalking.oap.server.core.query.DurationUtils;
 import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
-import org.apache.skywalking.oap.server.core.query.entity.ClusterBrief;
-import org.apache.skywalking.oap.server.core.query.entity.Database;
-import org.apache.skywalking.oap.server.core.query.entity.Endpoint;
-import org.apache.skywalking.oap.server.core.query.entity.EndpointInfo;
-import org.apache.skywalking.oap.server.core.query.entity.Service;
-import org.apache.skywalking.oap.server.core.query.entity.ServiceInstance;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.type.ClusterBrief;
+import org.apache.skywalking.oap.server.core.query.type.Database;
+import org.apache.skywalking.oap.server.core.query.type.Endpoint;
+import org.apache.skywalking.oap.server.core.query.type.EndpointInfo;
+import org.apache.skywalking.oap.server.core.query.type.Service;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstance;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
 public class MetadataQuery implements GraphQLQueryResolver {
@@ -55,33 +54,27 @@ public class MetadataQuery implements GraphQLQueryResolver {
         return metadataQueryService;
     }
 
+    /**
+     * @return all 0 of metadata.
+     */
+    @Deprecated
     public ClusterBrief getGlobalBrief(final Duration duration) throws IOException, ParseException {
-        long startTimestamp = DurationUtils.INSTANCE.startTimeToTimestamp(duration.getStep(), duration.getStart());
-        long endTimestamp = DurationUtils.INSTANCE.endTimeToTimestamp(duration.getStep(), duration.getEnd());
-
-        return getMetadataQueryService().getGlobalBrief(startTimestamp, endTimestamp);
+        return new ClusterBrief();
     }
 
     public List<Service> getAllServices(final Duration duration) throws IOException, ParseException {
-        long startTimestamp = DurationUtils.INSTANCE.startTimeToTimestamp(duration.getStep(), duration.getStart());
-        long endTimestamp = DurationUtils.INSTANCE.endTimeToTimestamp(duration.getStep(), duration.getEnd());
-
-        return getMetadataQueryService().getAllServices(startTimestamp, endTimestamp);
+        return getMetadataQueryService().getAllServices(duration.getStartTimestamp(), duration.getEndTimestamp());
     }
 
     public List<Service> getAllBrowserServices(final Duration duration) throws IOException, ParseException {
-        long startTimestamp = DurationUtils.INSTANCE.startTimeToTimestamp(duration.getStep(), duration.getStart());
-        long endTimestamp = DurationUtils.INSTANCE.endTimeToTimestamp(duration.getStep(), duration.getEnd());
-
-        return getMetadataQueryService().getAllBrowserServices(startTimestamp, endTimestamp);
+        return getMetadataQueryService().getAllBrowserServices(
+            duration.getStartTimestamp(), duration.getEndTimestamp());
     }
 
     public List<Service> searchServices(final Duration duration,
                                         final String keyword) throws IOException, ParseException {
-        long startTimestamp = DurationUtils.INSTANCE.startTimeToTimestamp(duration.getStep(), duration.getStart());
-        long endTimestamp = DurationUtils.INSTANCE.endTimeToTimestamp(duration.getStep(), duration.getEnd());
-
-        return getMetadataQueryService().searchServices(startTimestamp, endTimestamp, keyword);
+        return getMetadataQueryService().searchServices(
+            duration.getStartTimestamp(), duration.getEndTimestamp(), keyword);
     }
 
     public Service searchService(final String serviceCode) throws IOException {
@@ -90,10 +83,8 @@ public class MetadataQuery implements GraphQLQueryResolver {
 
     public List<ServiceInstance> getServiceInstances(final Duration duration,
                                                      final String serviceId) throws IOException, ParseException {
-        long startTimestamp = DurationUtils.INSTANCE.startTimeToTimestamp(duration.getStep(), duration.getStart());
-        long endTimestamp = DurationUtils.INSTANCE.endTimeToTimestamp(duration.getStep(), duration.getEnd());
-
-        return getMetadataQueryService().getServiceInstances(startTimestamp, endTimestamp, serviceId);
+        return getMetadataQueryService().getServiceInstances(
+            duration.getStartTimestamp(), duration.getEndTimestamp(), serviceId);
     }
 
     public List<Endpoint> searchEndpoint(final String keyword, final String serviceId,
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 7d776f5..4f293f7 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
@@ -21,77 +21,148 @@ package org.apache.skywalking.oap.query.graphql.resolver;
 import com.coxautodev.graphql.tools.GraphQLQueryResolver;
 import java.io.IOException;
 import java.text.ParseException;
+import java.util.ArrayList;
 import java.util.List;
+import lombok.RequiredArgsConstructor;
 import org.apache.skywalking.oap.query.graphql.type.BatchMetricConditions;
-import org.apache.skywalking.oap.query.graphql.type.Duration;
-import org.apache.skywalking.oap.query.graphql.type.MetricCondition;
-import org.apache.skywalking.oap.server.core.CoreModule;
-import org.apache.skywalking.oap.server.core.query.DurationUtils;
-import org.apache.skywalking.oap.server.core.query.MetricQueryService;
-import org.apache.skywalking.oap.server.core.query.StepToDownSampling;
-import org.apache.skywalking.oap.server.core.query.entity.IntValues;
-import org.apache.skywalking.oap.server.core.query.entity.Thermodynamic;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.Entity;
+import org.apache.skywalking.oap.server.core.query.input.MetricCondition;
+import org.apache.skywalking.oap.server.core.query.input.MetricsCondition;
+import org.apache.skywalking.oap.server.core.query.type.Bucket;
+import org.apache.skywalking.oap.server.core.query.type.HeatMap;
+import org.apache.skywalking.oap.server.core.query.type.IntValues;
+import org.apache.skywalking.oap.server.core.query.type.KVInt;
+import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
+import org.apache.skywalking.oap.server.core.query.type.Thermodynamic;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
+/**
+ * @since 8.0.0 This query is replaced by {@link MetricsQuery}
+ */
+@Deprecated
 public class MetricQuery implements GraphQLQueryResolver {
-
-    private final ModuleManager moduleManager;
-    private MetricQueryService metricQueryService;
+    private MetricsQuery query;
 
     public MetricQuery(ModuleManager moduleManager) {
-        this.moduleManager = moduleManager;
-    }
-
-    private MetricQueryService getMetricQueryService() {
-        if (metricQueryService == null) {
-            this.metricQueryService = moduleManager.find(CoreModule.NAME)
-                                                   .provider()
-                                                   .getService(MetricQueryService.class);
-        }
-        return metricQueryService;
+        query = new MetricsQuery(moduleManager);
     }
 
     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());
+        IntValues values = new IntValues();
+        if (metrics.getIds().size() == 0) {
+            KVInt kv = new KVInt();
+
+            MetricsCondition condition = new MetricsCondition();
+            condition.setName(metrics.getName());
+            condition.setEntity(new MockEntity(null));
+
+            kv.setValue(query.readMetricsValue(condition, duration));
+        } else {
+            for (final String id : metrics.getIds()) {
+                KVInt kv = new KVInt();
+                kv.setId(id);
+
+                MetricsCondition condition = new MetricsCondition();
+                condition.setName(metrics.getName());
+                condition.setEntity(new MockEntity(id));
+
+                kv.setValue(query.readMetricsValue(condition, duration));
+                values.addKVInt(kv);
+            }
+        }
 
-        return getMetricQueryService().getValues(metrics.getName(), metrics.getIds(), StepToDownSampling.transform(duration
-            .getStep()), startTimeBucket, endTimeBucket);
+        return values;
     }
 
     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());
+                                        final Duration duration) throws IOException, ParseException {
+
+        MetricsCondition condition = new MetricsCondition();
+        condition.setName(metrics.getName());
+        condition.setEntity(new MockEntity(metrics.getId()));
 
-        return getMetricQueryService().getLinearIntValues(metrics.getName(), metrics.getId(), StepToDownSampling.transform(duration
-            .getStep()), startTimeBucket, endTimeBucket);
+        final MetricsValues metricsValues = query.readMetricsValues(condition, duration);
+        return metricsValues.getValues();
     }
 
     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());
+                                                      final Duration duration) throws IOException, ParseException {
+        MetricsCondition condition = new MetricsCondition();
+        condition.setName(metrics.getName());
+        condition.setEntity(new MockEntity(metrics.getId()));
+
+        List<String> labels = new ArrayList<>(numOfLinear);
+        for (int i = 0; i < numOfLinear; i++) {
+            labels.add(String.valueOf(i));
+        }
+
+        final List<MetricsValues> metricsValues = query.readLabeledMetricsValues(condition, labels, duration);
+        List<IntValues> response = new ArrayList<>(metricsValues.size());
+        metricsValues.forEach(value -> {
+            response.add(value.getValues());
+        });
 
-        return getMetricQueryService().getMultipleLinearIntValues(metrics.getName(), metrics.getId(), numOfLinear, StepToDownSampling
-            .transform(duration.getStep()), startTimeBucket, endTimeBucket);
+        return response;
     }
 
     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());
-
-        return getMetricQueryService().getSubsetOfMultipleLinearIntValues(metrics.getName(), metrics.getId(), linearIndex, StepToDownSampling
-            .transform(duration.getStep()), startTimeBucket, endTimeBucket);
+                                                              final List<Integer> linearIndex,
+                                                              final Duration duration) throws IOException, ParseException {
+        MetricsCondition condition = new MetricsCondition();
+        condition.setName(metrics.getName());
+        condition.setEntity(new MockEntity(metrics.getId()));
+
+        List<String> labels = new ArrayList<>(linearIndex.size());
+        linearIndex.forEach(i -> labels.add(String.valueOf(i)));
+
+        final List<MetricsValues> metricsValues = query.readLabeledMetricsValues(condition, labels, duration);
+        List<IntValues> response = new ArrayList<>(metricsValues.size());
+        metricsValues.forEach(value -> {
+            response.add(value.getValues());
+        });
+
+        return response;
     }
 
     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());
+                                          final Duration duration) throws IOException, ParseException {
+        MetricsCondition condition = new MetricsCondition();
+        condition.setName(metrics.getName());
+        condition.setEntity(new MockEntity(metrics.getId()));
+
+        final HeatMap heatMap = query.readHeatMap(condition, duration);
+
+        Thermodynamic thermodynamic = new Thermodynamic();
+        final List<Bucket> buckets = heatMap.getBuckets();
+
+        if (buckets.size() > 1) {
+            // Use the first bucket size as the axis Y step, because in the previous(before 8.x),
+            // We only use equilong bucket.
+            // Use 1 to avoid `infinite-` as bucket#min
+            thermodynamic.setAxisYStep(buckets.get(1).duration());
+        } else {
+            // Used to be a static config.
+            thermodynamic.setAxisYStep(200);
+        }
+
+        for (int x = 0; x < heatMap.getValues().size(); x++) {
+            final HeatMap.HeatMapColumn heatMapColumn = heatMap.getValues().get(x);
+            for (int y = 0; y < heatMapColumn.getValues().size(); y++) {
+                thermodynamic.addNodeValue(x, y, heatMapColumn.getValues().get(y));
+            }
+        }
 
-        return getMetricQueryService().getThermodynamic(metrics.getName(), metrics.getId(), StepToDownSampling.transform(duration
-            .getStep()), startTimeBucket, endTimeBucket);
+        return thermodynamic;
+    }
+
+    @RequiredArgsConstructor
+    private static class MockEntity extends Entity {
+        private final String id;
+
+        @Override
+        public String buildId() {
+            return id;
+        }
     }
 }
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
new file mode 100644
index 0000000..b450a3c
--- /dev/null
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsQuery.java
@@ -0,0 +1,141 @@
+/*
+ * 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.skywalking.oap.query.graphql.resolver;
+
+import com.coxautodev.graphql.tools.GraphQLQueryResolver;
+import java.io.IOException;
+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.MetricsQueryService;
+import org.apache.skywalking.oap.server.core.query.TopNRecordsQueryService;
+import org.apache.skywalking.oap.server.core.query.enumeration.MetricsType;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.MetricsCondition;
+import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
+import org.apache.skywalking.oap.server.core.query.type.HeatMap;
+import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
+import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
+
+/**
+ * Metrics v2 query protocol implementation.
+ *
+ * @since 8.0.0
+ */
+public class MetricsQuery implements GraphQLQueryResolver {
+    private final ModuleManager moduleManager;
+    private MetricsQueryService metricsQueryService;
+    private AggregationQueryService queryService;
+    private TopNRecordsQueryService topNRecordsQueryService;
+
+    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;
+    }
+
+    private TopNRecordsQueryService getTopNRecordsQueryService() {
+        if (topNRecordsQueryService == null) {
+            this.topNRecordsQueryService = moduleManager.find(CoreModule.NAME)
+                                                        .provider()
+                                                        .getService(TopNRecordsQueryService.class);
+        }
+        return topNRecordsQueryService;
+    }
+
+    private MetricsQueryService getMetricsQueryService() {
+        if (metricsQueryService == null) {
+            this.metricsQueryService = moduleManager.find(CoreModule.NAME)
+                                                    .provider()
+                                                    .getService(MetricsQueryService.class);
+        }
+        return metricsQueryService;
+    }
+
+    /**
+     * Metrics definition metadata query. Response the metrics type which determines the suitable query methods.
+     */
+    public MetricsType typeOfMetrics(String name) throws IOException {
+        return MetricsType.UNKNOWN;
+    }
+
+    /**
+     * Read metrics single value in the duration of required metrics
+     */
+    public int readMetricsValue(MetricsCondition condition, Duration duration) throws IOException {
+        return getMetricsQueryService().readMetricsValue(condition, duration);
+    }
+
+    /**
+     * Read time-series values in the duration of required metrics
+     */
+    public MetricsValues readMetricsValues(MetricsCondition condition, Duration duration) throws IOException {
+        return getMetricsQueryService().readMetricsValues(condition, duration);
+    }
+
+    /**
+     * Read entity list of required metrics and parent entity type.
+     */
+    public List<SelectedRecord> sortMetrics(TopNCondition condition, Duration duration) throws IOException {
+        return getQueryService().sortMetrics(condition, duration);
+    }
+
+    /**
+     * Read value in the given time duration, usually as a linear.
+     *
+     * @param labels the labels you need to query.
+     */
+    public List<MetricsValues> readLabeledMetricsValues(MetricsCondition condition,
+                                                        List<String> labels,
+                                                        Duration duration) throws IOException {
+        return getMetricsQueryService().readLabeledMetricsValues(condition, labels, duration);
+    }
+
+    /**
+     * Heatmap is bucket based value statistic result.
+     *
+     * @return heapmap including the latency distribution
+     * {@link HeatMap#getBuckets()}
+     * {@link HeatMap.HeatMapColumn#getValues()} follows this rule.
+     * <pre>
+     *      key = 0, represents [0, 100), value = count of requests in the latency range.
+     *      key = 100, represents [100, 200), value = count of requests in the latency range.
+     *      ...
+     *      key = step * maxNumOfSteps, represents [step * maxNumOfSteps, MAX)
+     * </pre>
+     */
+    public HeatMap readHeatMap(MetricsCondition condition, Duration duration) throws IOException {
+        return getMetricsQueryService().readHeatMap(condition, duration);
+    }
+
+    /**
+     * Read the sampled records.
+     */
+    public List<SelectedRecord> readSampledRecords(TopNCondition condition, Duration duration) throws IOException {
+        return getTopNRecordsQueryService().readSampledRecords(condition, duration);
+    }
+}
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/Mutation.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/Mutation.java
index cf3abdb..239588f 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/Mutation.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/Mutation.java
@@ -24,5 +24,5 @@ import com.coxautodev.graphql.tools.GraphQLMutationResolver;
  * Root mutation resolver.
  */
 public class Mutation implements GraphQLMutationResolver {
-    private String version;
+    private String version = "8.0";
 }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileMutation.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileMutation.java
index f65a70d..1677d94 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileMutation.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileMutation.java
@@ -20,10 +20,10 @@ package org.apache.skywalking.oap.query.graphql.resolver;
 
 import com.coxautodev.graphql.tools.GraphQLMutationResolver;
 import java.io.IOException;
-import org.apache.skywalking.oap.query.graphql.type.ProfileTaskCreationRequest;
+import org.apache.skywalking.oap.server.core.query.input.ProfileTaskCreationRequest;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.profile.ProfileTaskMutationService;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskCreationResult;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskCreationResult;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
 /**
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java
index bb9ae5d..2edcd1c 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java
@@ -21,11 +21,11 @@ package org.apache.skywalking.oap.query.graphql.resolver;
 import com.coxautodev.graphql.tools.GraphQLQueryResolver;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.query.ProfileTaskQueryService;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzation;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
-import org.apache.skywalking.oap.server.core.query.entity.ProfiledSegment;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzation;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzeTimeRange;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfiledSegment;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
 import java.io.IOException;
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/Query.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/Query.java
index 8f4a018..947e303 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/Query.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/Query.java
@@ -24,5 +24,5 @@ import com.coxautodev.graphql.tools.GraphQLQueryResolver;
  * Root Query Resolver.
  */
 public class Query implements GraphQLQueryResolver {
-    private String version = "6.0";
+    private String version = "8.0";
 }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopNRecordsQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopNRecordsQuery.java
index c5eb040..0fbc347 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopNRecordsQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopNRecordsQuery.java
@@ -20,43 +20,47 @@ 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.query.graphql.type.TopNRecordsCondition;
-import org.apache.skywalking.oap.server.core.CoreModule;
-import org.apache.skywalking.oap.server.core.query.DurationUtils;
-import org.apache.skywalking.oap.server.core.query.TopNRecordsQueryService;
-import org.apache.skywalking.oap.server.core.query.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNRecord;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
+import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
+import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
+import org.apache.skywalking.oap.server.core.query.type.TopNRecord;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
+/**
+ * @since 8.0.0 This query is replaced by {@link MetricsQuery}, all queries have been delegated to there.
+ */
+@Deprecated
 public class TopNRecordsQuery implements GraphQLQueryResolver {
-    private final ModuleManager moduleManager;
-    private TopNRecordsQueryService topNRecordsQueryService;
+    private MetricsQuery query;
 
     public TopNRecordsQuery(ModuleManager moduleManager) {
-        this.moduleManager = moduleManager;
-    }
-
-    private TopNRecordsQueryService getTopNRecordsQueryService() {
-        if (topNRecordsQueryService == null) {
-            this.topNRecordsQueryService = moduleManager.find(CoreModule.NAME)
-                                                        .provider()
-                                                        .getService(TopNRecordsQueryService.class);
-        }
-        return topNRecordsQueryService;
+        query = new MetricsQuery(moduleManager);
     }
 
     public List<TopNRecord> getTopNRecords(TopNRecordsCondition condition) throws IOException {
-        long startSecondTB = DurationUtils.INSTANCE.startTimeDurationToSecondTimeBucket(
-            condition.getDuration().getStep(), condition.getDuration().getStart());
-        long endSecondTB = DurationUtils.INSTANCE.endTimeDurationToSecondTimeBucket(
-            condition.getDuration().getStep(), condition.getDuration().getEnd());
-
-        String metricName = condition.getMetricName();
-        Order order = condition.getOrder();
-        int topN = condition.getTopN();
+        TopNCondition topNCondition = new TopNCondition();
+        topNCondition.setName(condition.getMetricName());
+        final IDManager.ServiceID.ServiceIDDefinition serviceIDDefinition = IDManager.ServiceID.analysisId(
+            condition.getServiceId());
+        topNCondition.setParentService(serviceIDDefinition.getName());
+        topNCondition.setNormal(serviceIDDefinition.isReal());
+        // Scope is not required in topN record query.
+        // topNCondition.setScope();
+        topNCondition.setOrder(condition.getOrder());
+        topNCondition.setTopN(condition.getTopN());
 
-        return getTopNRecordsQueryService().getTopNRecords(
-            startSecondTB, endSecondTB, metricName, condition.getServiceId(), topN, order);
+        final List<SelectedRecord> selectedRecords = query.readSampledRecords(topNCondition, condition.getDuration());
+        List<TopNRecord> list = new ArrayList<>(selectedRecords.size());
+        selectedRecords.forEach(record -> {
+            TopNRecord top = new TopNRecord();
+            top.setStatement(record.getName());
+            top.setTraceId(record.getRefId());
+            top.setLatency(Long.parseLong(record.getValue()));
+            list.add(top);
+        });
+        return list;
     }
 }
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 71a8bcf..333c962 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
@@ -22,13 +22,11 @@ import com.coxautodev.graphql.tools.GraphQLQueryResolver;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.skywalking.oap.query.graphql.type.Duration;
 import org.apache.skywalking.oap.server.core.CoreModule;
-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.query.TopologyQueryService;
-import org.apache.skywalking.oap.server.core.query.entity.ServiceInstanceTopology;
-import org.apache.skywalking.oap.server.core.query.entity.Topology;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstanceTopology;
+import org.apache.skywalking.oap.server.core.query.type.Topology;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
 public class TopologyQuery implements GraphQLQueryResolver {
@@ -48,11 +46,7 @@ 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());
-
-        return getQueryService().getGlobalTopology(
-            StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket);
+        return getQueryService().getGlobalTopology(duration.getStartTimeBucket(), duration.getEndTimeBucket());
     }
 
     public Topology getServiceTopology(final String serviceId, final Duration duration) throws IOException {
@@ -62,30 +56,21 @@ 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());
-
         return getQueryService().getServiceTopology(
-            StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket, serviceIds);
+            duration.getStartTimeBucket(), duration.getEndTimeBucket(), serviceIds);
     }
 
-    public ServiceInstanceTopology getServiceInstanceTopology(final String clientServiceId, final String serverServiceId,
+    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());
-
         return getQueryService().getServiceInstanceTopology(
-            clientServiceId, serverServiceId, StepToDownSampling.transform(duration
-                                                                               .getStep()), startTimeBucket,
-            endTimeBucket
+            clientServiceId, serverServiceId,
+            duration.getStartTimeBucket(), duration.getEndTimeBucket()
         );
     }
 
     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());
-
         return getQueryService().getEndpointTopology(
-            StepToDownSampling.transform(duration.getStep()), startTimeBucket, endTimeBucket, endpointId);
+            duration.getStartTimeBucket(), duration.getEndTimeBucket(), endpointId);
     }
 }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java
index 58df22b..804334e 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java
@@ -21,17 +21,16 @@ package org.apache.skywalking.oap.query.graphql.resolver;
 import com.coxautodev.graphql.tools.GraphQLQueryResolver;
 import com.google.common.base.Strings;
 import java.io.IOException;
-import org.apache.skywalking.oap.query.graphql.type.TraceQueryCondition;
 import org.apache.skywalking.oap.server.core.Const;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.UnexpectedException;
-import org.apache.skywalking.oap.server.core.query.DurationUtils;
 import org.apache.skywalking.oap.server.core.query.TraceQueryService;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.Trace;
-import org.apache.skywalking.oap.server.core.query.entity.TraceBrief;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.input.TraceQueryCondition;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.Trace;
+import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
 import static java.util.Objects.nonNull;
@@ -60,14 +59,8 @@ public class TraceQuery implements GraphQLQueryResolver {
         if (!Strings.isNullOrEmpty(condition.getTraceId())) {
             traceId = condition.getTraceId();
         } else if (nonNull(condition.getQueryDuration())) {
-            startSecondTB = DurationUtils.INSTANCE.startTimeDurationToSecondTimeBucket(
-                condition.getQueryDuration()
-                         .getStep(), condition.getQueryDuration()
-                                              .getStart());
-            endSecondTB = DurationUtils.INSTANCE.endTimeDurationToSecondTimeBucket(
-                condition.getQueryDuration()
-                         .getStep(), condition.getQueryDuration()
-                                              .getEnd());
+            startSecondTB = condition.getQueryDuration().getStartTimeBucketInSec();
+            endSecondTB = condition.getQueryDuration().getEndTimeBucketInSec();
         } else {
             throw new UnexpectedException("The condition must contains either queryDuration or traceId.");
         }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/BatchMetricConditions.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/BatchMetricConditions.java
index f76dcf8..64ebb26 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/BatchMetricConditions.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/BatchMetricConditions.java
@@ -22,9 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 import lombok.Getter;
 
-/**
- *
- **/
+@Deprecated
 @Getter
 public class BatchMetricConditions {
     private String name;
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/Duration.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/Duration.java
deleted file mode 100644
index b73142b..0000000
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/Duration.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.skywalking.oap.query.graphql.type;
-
-import lombok.Getter;
-import org.apache.skywalking.oap.server.core.query.entity.Step;
-
-@Getter
-public class Duration {
-    private String start;
-    private String end;
-    private Step step;
-}
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/TopNRecordsCondition.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/TopNRecordsCondition.java
index 8daf081..ede62a2 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/TopNRecordsCondition.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/type/TopNRecordsCondition.java
@@ -20,8 +20,10 @@ package org.apache.skywalking.oap.query.graphql.type;
 
 import lombok.Getter;
 import lombok.Setter;
-import org.apache.skywalking.oap.server.core.query.entity.Order;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.enumeration.Order;
 
+@Deprecated
 @Getter
 @Setter
 public class TopNRecordsCondition {
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 707ae9d..c27d393 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 707ae9de94973ed15f8cb2ced15171e6f6193e03
+Subproject commit c27d39381860e56bb9aec0d4377bb256641fdf26
diff --git a/oap-server/server-receiver-plugin/skywalking-profile-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/profile/provider/handler/ProfileTaskServiceHandler.java b/oap-server/server-receiver-plugin/skywalking-profile-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/profile/provider/handler/ProfileTaskServiceHandler.java
index ab172a2..0caa644 100644
--- a/oap-server/server-receiver-plugin/skywalking-profile-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/profile/provider/handler/ProfileTaskServiceHandler.java
+++ b/oap-server/server-receiver-plugin/skywalking-profile-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/profile/provider/handler/ProfileTaskServiceHandler.java
@@ -34,8 +34,8 @@ import org.apache.skywalking.oap.server.core.cache.ProfileTaskCache;
 import org.apache.skywalking.oap.server.core.command.CommandService;
 import org.apache.skywalking.oap.server.core.profile.ProfileTaskLogRecord;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLogOperationType;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLogOperationType;
 import org.apache.skywalking.oap.server.core.analysis.NodeType;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 import org.apache.skywalking.oap.server.library.server.grpc.GRPCHandler;
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ColumnTypeEsMapping.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ColumnTypeEsMapping.java
index 45dc635..7eefe65 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ColumnTypeEsMapping.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ColumnTypeEsMapping.java
@@ -20,7 +20,7 @@ package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base;
 
 import com.google.gson.JsonObject;
 import org.apache.skywalking.oap.server.core.analysis.NodeType;
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValueHashMap;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 import org.apache.skywalking.oap.server.core.storage.model.DataTypeMapping;
 
 public class ColumnTypeEsMapping implements DataTypeMapping {
@@ -35,7 +35,7 @@ public class ColumnTypeEsMapping implements DataTypeMapping {
             return "double";
         } else if (String.class.equals(type)) {
             return "keyword";
-        } else if (IntKeyLongValueHashMap.class.equals(type)) {
+        } else if (DataTable.class.equals(type)) {
             return "text";
         } else if (byte[].class.equals(type)) {
             return "binary";
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/EsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/EsDAO.java
index 7242a99..396e71c 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/EsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/EsDAO.java
@@ -20,17 +20,11 @@ package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base;
 
 import java.io.IOException;
 import java.util.Map;
-import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
-import org.apache.skywalking.oap.server.core.query.sql.Where;
 import org.apache.skywalking.oap.server.core.storage.AbstractDAO;
 import org.apache.skywalking.oap.server.core.storage.type.StorageDataComplexObject;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
-import org.elasticsearch.index.query.BoolQueryBuilder;
-import org.elasticsearch.index.query.QueryBuilders;
-import org.elasticsearch.index.query.RangeQueryBuilder;
-import org.elasticsearch.search.builder.SearchSourceBuilder;
 
 public abstract class EsDAO extends AbstractDAO<ElasticSearchClient> {
 
@@ -38,26 +32,6 @@ public abstract class EsDAO extends AbstractDAO<ElasticSearchClient> {
         super(client);
     }
 
-    protected final void queryBuild(SearchSourceBuilder sourceBuilder, Where where, long startTB, long endTB) {
-        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(Metrics.TIME_BUCKET).gte(startTB).lte(endTB);
-        if (where.getKeyValues().isEmpty()) {
-            sourceBuilder.query(rangeQueryBuilder);
-        } else {
-            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
-            boolQuery.must().add(rangeQueryBuilder);
-
-            where.getKeyValues().forEach(keyValues -> {
-                if (keyValues.getValues().size() > 1) {
-                    boolQuery.must().add(QueryBuilders.termsQuery(keyValues.getKey(), keyValues.getValues()));
-                } else {
-                    boolQuery.must().add(QueryBuilders.termQuery(keyValues.getKey(), keyValues.getValues().get(0)));
-                }
-            });
-            sourceBuilder.query(boolQuery);
-        }
-        sourceBuilder.size(0);
-    }
-
     protected XContentBuilder map2builder(Map<String, Object> objectMap) throws IOException {
         XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
         for (String key : objectMap.keySet()) {
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AggregationQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AggregationQueryEsDAO.java
index 4d538bc..c1d4ce3 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AggregationQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AggregationQueryEsDAO.java
@@ -21,22 +21,20 @@ package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.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.oap.server.core.analysis.manual.endpoint.EndpointTraffic;
-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.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNEntity;
+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.storage.query.IAggregationQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
 import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.index.query.BoolQueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.aggregations.AggregationBuilders;
 import org.elasticsearch.search.aggregations.BucketOrder;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
-import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
 import org.elasticsearch.search.aggregations.metrics.avg.Avg;
 import org.elasticsearch.search.builder.SearchSourceBuilder;
 
@@ -47,105 +45,41 @@ public class AggregationQueryEsDAO extends EsDAO implements IAggregationQueryDAO
     }
 
     @Override
-    public List<TopNEntity> getServiceTopN(String indexName, String valueCName, int topN, DownSampling downsampling,
-                                           long startTB, long endTB, Order order) throws IOException {
+    public List<SelectedRecord> sortMetrics(final TopNCondition condition,
+                                            final String valueColumnName,
+                                            final Duration duration,
+                                            final List<KeyValue> additionalConditions) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-        sourceBuilder.query(QueryBuilders.rangeQuery(Metrics.TIME_BUCKET).lte(endTB).gte(startTB));
-        return aggregation(indexName, valueCName, sourceBuilder, topN, order);
-    }
+        sourceBuilder.query(QueryBuilders.rangeQuery(Metrics.TIME_BUCKET)
+                                         .lte(duration.getEndTimeBucket())
+                                         .gte(duration.getStartTimeBucket()));
 
-    @Override
-    public List<TopNEntity> getAllServiceInstanceTopN(String indexName,
-                                                      String valueCName,
-                                                      int topN,
-                                                      DownSampling downsampling,
-                                                      long startTB,
-                                                      long endTB,
-                                                      Order order) throws IOException {
-        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-        sourceBuilder.query(QueryBuilders.rangeQuery(Metrics.TIME_BUCKET).lte(endTB).gte(startTB));
-        return aggregation(indexName, valueCName, sourceBuilder, topN, order);
-    }
-
-    @Override
-    public List<TopNEntity> getServiceInstanceTopN(String serviceId,
-                                                   String indexName,
-                                                   String valueCName,
-                                                   int topN,
-                                                   DownSampling downsampling,
-                                                   long startTB,
-                                                   long endTB,
-                                                   Order order) throws IOException {
-        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-
-        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
-        sourceBuilder.query(boolQueryBuilder);
-
-        boolQueryBuilder.must().add(QueryBuilders.rangeQuery(Metrics.TIME_BUCKET).lte(endTB).gte(startTB));
-        boolQueryBuilder.must().add(QueryBuilders.termQuery(InstanceTraffic.SERVICE_ID, serviceId));
-
-        return aggregation(indexName, valueCName, sourceBuilder, topN, order);
-    }
-
-    @Override
-    public List<TopNEntity> getAllEndpointTopN(String indexName, String valueCName, int topN, DownSampling downsampling,
-                                               long startTB, long endTB, Order order) throws IOException {
-        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-        sourceBuilder.query(QueryBuilders.rangeQuery(Metrics.TIME_BUCKET).lte(endTB).gte(startTB));
-        return aggregation(indexName, valueCName, sourceBuilder, topN, order);
-    }
-
-    @Override
-    public List<TopNEntity> getEndpointTopN(String serviceId,
-                                            String indexName,
-                                            String valueCName,
-                                            int topN,
-                                            DownSampling downsampling,
-                                            long startTB,
-                                            long endTB,
-                                            Order order) throws IOException {
-        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-
-        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
-        sourceBuilder.query(boolQueryBuilder);
-
-        boolQueryBuilder.must().add(QueryBuilders.rangeQuery(Metrics.TIME_BUCKET).lte(endTB).gte(startTB));
-        boolQueryBuilder.must().add(QueryBuilders.termQuery(EndpointTraffic.SERVICE_ID, serviceId));
-
-        return aggregation(indexName, valueCName, sourceBuilder, topN, order);
-    }
-
-    protected List<TopNEntity> aggregation(String indexName, String valueCName, SearchSourceBuilder sourceBuilder,
-                                           int topN, Order order) throws IOException {
         boolean asc = false;
-        if (order.equals(Order.ASC)) {
+        if (condition.getOrder().equals(Order.ASC)) {
             asc = true;
         }
 
-        TermsAggregationBuilder aggregationBuilder = aggregationBuilder(valueCName, topN, asc);
-
-        sourceBuilder.aggregation(aggregationBuilder);
+        sourceBuilder.aggregation(
+            AggregationBuilders.terms(Metrics.ENTITY_ID)
+                               .field(Metrics.ENTITY_ID)
+                               .order(BucketOrder.aggregation(valueColumnName, asc))
+                               .size(condition.getTopN())
+                               .subAggregation(AggregationBuilders.avg(valueColumnName).field(valueColumnName))
+        );
 
-        SearchResponse response = getClient().search(indexName, sourceBuilder);
+        SearchResponse response = getClient().search(condition.getName(), sourceBuilder);
 
-        List<TopNEntity> topNEntities = new ArrayList<>();
+        List<SelectedRecord> topNList = new ArrayList<>();
         Terms idTerms = response.getAggregations().get(Metrics.ENTITY_ID);
         for (Terms.Bucket termsBucket : idTerms.getBuckets()) {
-            TopNEntity topNEntity = new TopNEntity();
-            topNEntity.setId(termsBucket.getKeyAsString());
-            Avg value = termsBucket.getAggregations().get(valueCName);
-            topNEntity.setValue((long) value.getValue());
-            topNEntities.add(topNEntity);
+            SelectedRecord record = new SelectedRecord();
+            record.setId(termsBucket.getKeyAsString());
+            Avg value = termsBucket.getAggregations().get(valueColumnName);
+            record.setValue(String.valueOf((long) value.getValue()));
+            topNList.add(record);
         }
 
-        return topNEntities;
+        return topNList;
     }
 
-    protected TermsAggregationBuilder aggregationBuilder(final String valueCName, final int topN, final boolean asc) {
-        return AggregationBuilders.terms(Metrics.ENTITY_ID)
-                                  .field(Metrics.ENTITY_ID)
-                                  .order(BucketOrder.aggregation(valueCName, asc))
-                                  .size(topN)
-                                  .subAggregation(AggregationBuilders.avg(valueCName).field(valueCName));
-    }
 }
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AlarmQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AlarmQueryEsDAO.java
index 4cf4c6c..f3517d2 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AlarmQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AlarmQueryEsDAO.java
@@ -22,9 +22,9 @@ import com.google.common.base.Strings;
 import java.io.IOException;
 import java.util.Objects;
 import org.apache.skywalking.oap.server.core.alarm.AlarmRecord;
-import org.apache.skywalking.oap.server.core.query.entity.AlarmMessage;
-import org.apache.skywalking.oap.server.core.query.entity.Alarms;
-import org.apache.skywalking.oap.server.core.query.entity.Scope;
+import org.apache.skywalking.oap.server.core.query.type.AlarmMessage;
+import org.apache.skywalking.oap.server.core.query.type.Alarms;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
 import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/LogQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/LogQueryEsDAO.java
index 2a5edf8..7310cad 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/LogQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/LogQueryEsDAO.java
@@ -25,11 +25,11 @@ import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.Const;
 import org.apache.skywalking.oap.server.core.analysis.manual.log.AbstractLogRecord;
 import org.apache.skywalking.oap.server.core.analysis.record.Record;
-import org.apache.skywalking.oap.server.core.query.entity.ContentType;
-import org.apache.skywalking.oap.server.core.query.entity.Log;
-import org.apache.skywalking.oap.server.core.query.entity.LogState;
-import org.apache.skywalking.oap.server.core.query.entity.Logs;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.ContentType;
+import org.apache.skywalking.oap.server.core.query.type.Log;
+import org.apache.skywalking.oap.server.core.query.type.LogState;
+import org.apache.skywalking.oap.server.core.query.type.Logs;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
 import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetadataQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetadataQueryEsDAO.java
index 6bd9c16..8f543d2 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetadataQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetadataQueryEsDAO.java
@@ -19,7 +19,6 @@
 package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query;
 
 import com.google.common.base.Strings;
-import com.google.gson.Gson;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import java.io.IOException;
@@ -32,13 +31,12 @@ import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
 import org.apache.skywalking.oap.server.core.analysis.manual.endpoint.EndpointTraffic;
 import org.apache.skywalking.oap.server.core.analysis.manual.instance.InstanceTraffic;
 import org.apache.skywalking.oap.server.core.analysis.manual.service.ServiceTraffic;
-import org.apache.skywalking.oap.server.core.query.entity.Attribute;
-import org.apache.skywalking.oap.server.core.query.entity.Database;
-import org.apache.skywalking.oap.server.core.query.entity.Endpoint;
-import org.apache.skywalking.oap.server.core.query.entity.Language;
-import org.apache.skywalking.oap.server.core.query.entity.LanguageTrans;
-import org.apache.skywalking.oap.server.core.query.entity.Service;
-import org.apache.skywalking.oap.server.core.query.entity.ServiceInstance;
+import org.apache.skywalking.oap.server.core.query.enumeration.Language;
+import org.apache.skywalking.oap.server.core.query.type.Attribute;
+import org.apache.skywalking.oap.server.core.query.type.Database;
+import org.apache.skywalking.oap.server.core.query.type.Endpoint;
+import org.apache.skywalking.oap.server.core.query.type.Service;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstance;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
@@ -53,8 +51,6 @@ import org.elasticsearch.search.builder.SearchSourceBuilder;
 import static org.apache.skywalking.oap.server.core.analysis.manual.instance.InstanceTraffic.PropertyUtil.LANGUAGE;
 
 public class MetadataQueryEsDAO extends EsDAO implements IMetadataQueryDAO {
-    private static final Gson GSON = new Gson();
-
     private final int queryMaxSize;
 
     public MetadataQueryEsDAO(ElasticSearchClient client, int queryMaxSize) {
@@ -63,47 +59,6 @@ public class MetadataQueryEsDAO extends EsDAO implements IMetadataQueryDAO {
     }
 
     @Override
-    public int numOfService(long startTimestamp, long endTimestamp) throws IOException {
-        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-
-        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
-        boolQueryBuilder.must().add(QueryBuilders.termQuery(ServiceTraffic.NODE_TYPE, NodeType.Normal.value()));
-        sourceBuilder.query(boolQueryBuilder);
-        sourceBuilder.size(0);
-
-        SearchResponse response = getClient().search(ServiceTraffic.INDEX_NAME, sourceBuilder);
-        return (int) response.getHits().getTotalHits();
-    }
-
-    /**
-     * @since 7.0.0, as EndpointInventory has been replaced by EndpointTraffic. This is not an accurate number anymore.
-     */
-    @Override
-    public int numOfEndpoint() throws IOException {
-        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-
-        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
-
-        sourceBuilder.query(boolQueryBuilder);
-        sourceBuilder.size(0);
-
-        SearchResponse response = getClient().search(EndpointTraffic.INDEX_NAME, sourceBuilder);
-        return (int) response.getHits().getTotalHits();
-    }
-
-    @Override
-    public int numOfConjectural(int nodeTypeValue) throws IOException {
-        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-
-        sourceBuilder.query(QueryBuilders.termQuery(ServiceTraffic.NODE_TYPE, nodeTypeValue));
-        sourceBuilder.size(0);
-
-        SearchResponse response = getClient().search(ServiceTraffic.INDEX_NAME, sourceBuilder);
-
-        return (int) response.getHits().getTotalHits();
-    }
-
-    @Override
     public List<Service> getAllServices(long startTimestamp, long endTimestamp) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
 
@@ -255,7 +210,7 @@ public class MetadataQueryEsDAO extends EsDAO implements IMetadataQueryDAO {
                     String key = property.getKey();
                     String value = property.getValue().getAsString();
                     if (key.equals(LANGUAGE)) {
-                        serviceInstance.setLanguage(LanguageTrans.INSTANCE.value(value));
+                        serviceInstance.setLanguage(Language.value(value));
                     } else {
                         serviceInstance.getAttributes().add(new Attribute(key, value));
                     }
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetricsQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetricsQueryEsDAO.java
index 4a31918..278e19d 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetricsQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetricsQueryEsDAO.java
@@ -23,20 +23,25 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValue;
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValueHashMap;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
+import org.apache.skywalking.oap.server.core.analysis.metrics.HistogramMetrics;
 import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
-import org.apache.skywalking.oap.server.core.analysis.metrics.ThermodynamicMetrics;
-import org.apache.skywalking.oap.server.core.query.entity.IntValues;
-import org.apache.skywalking.oap.server.core.query.entity.KVInt;
-import org.apache.skywalking.oap.server.core.query.entity.Thermodynamic;
+import org.apache.skywalking.oap.server.core.query.PointOfTime;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.MetricsCondition;
 import org.apache.skywalking.oap.server.core.query.sql.Function;
-import org.apache.skywalking.oap.server.core.query.sql.Where;
+import org.apache.skywalking.oap.server.core.query.type.HeatMap;
+import org.apache.skywalking.oap.server.core.query.type.IntValues;
+import org.apache.skywalking.oap.server.core.query.type.KVInt;
+import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
+import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.index.query.BoolQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.index.query.RangeQueryBuilder;
 import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.aggregations.AggregationBuilders;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
@@ -52,158 +57,186 @@ public class MetricsQueryEsDAO extends EsDAO implements IMetricsQueryDAO {
     }
 
     @Override
-    public IntValues getValues(String indexName, DownSampling downsampling, long startTB, long endTB, Where where,
-                               String valueCName, Function function) throws IOException {
+    public int readMetricsValue(final MetricsCondition condition,
+                                final String valueColumnName,
+                                final Duration duration) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-        queryBuild(sourceBuilder, where, startTB, endTB);
+        buildQuery(sourceBuilder, condition, duration);
 
         TermsAggregationBuilder entityIdAggregation = AggregationBuilders.terms(Metrics.ENTITY_ID)
                                                                          .field(Metrics.ENTITY_ID)
-                                                                         .size(1000);
-        functionAggregation(function, entityIdAggregation, valueCName);
+                                                                         .size(1);
+        final Function function = ValueColumnMetadata.INSTANCE.getValueFunction(condition.getName());
+        functionAggregation(function, entityIdAggregation, valueColumnName);
 
         sourceBuilder.aggregation(entityIdAggregation);
 
-        SearchResponse response = getClient().search(indexName, sourceBuilder);
+        SearchResponse response = getClient().search(condition.getName(), sourceBuilder);
 
-        IntValues intValues = new IntValues();
         Terms idTerms = response.getAggregations().get(Metrics.ENTITY_ID);
         for (Terms.Bucket idBucket : idTerms.getBuckets()) {
-            long value;
             switch (function) {
                 case Sum:
-                    Sum sum = idBucket.getAggregations().get(valueCName);
-                    value = (long) sum.getValue();
-                    break;
+                    Sum sum = idBucket.getAggregations().get(valueColumnName);
+                    return (int) sum.getValue();
                 case Avg:
-                    Avg avg = idBucket.getAggregations().get(valueCName);
-                    value = (long) avg.getValue();
-                    break;
+                    Avg avg = idBucket.getAggregations().get(valueColumnName);
+                    return (int) avg.getValue();
                 default:
-                    avg = idBucket.getAggregations().get(valueCName);
-                    value = (long) avg.getValue();
-                    break;
+                    avg = idBucket.getAggregations().get(valueColumnName);
+                    return (int) avg.getValue();
             }
-
-            KVInt kvInt = new KVInt();
-            kvInt.setId(idBucket.getKeyAsString());
-            kvInt.setValue(value);
-            intValues.addKVInt(kvInt);
-        }
-
-        return intValues;
-    }
-
-    protected void functionAggregation(Function function, TermsAggregationBuilder parentAggBuilder, String valueCName) {
-        switch (function) {
-            case Avg:
-                parentAggBuilder.subAggregation(AggregationBuilders.avg(valueCName).field(valueCName));
-                break;
-            case Sum:
-                parentAggBuilder.subAggregation(AggregationBuilders.sum(valueCName).field(valueCName));
-                break;
-            default:
-                parentAggBuilder.subAggregation(AggregationBuilders.avg(valueCName).field(valueCName));
-                break;
         }
+        return ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName());
     }
 
     @Override
-    public IntValues getLinearIntValues(String indexName, DownSampling downsampling, List<String> ids,
-                                        String valueCName) throws IOException {
-        SearchResponse response = getClient().ids(indexName, ids.toArray(new String[0]));
+    public MetricsValues readMetricsValues(final MetricsCondition condition,
+                                           final String valueColumnName,
+                                           final Duration duration) throws IOException {
+        final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
+        List<String> ids = new ArrayList<>(pointOfTimes.size());
+        pointOfTimes.forEach(pointOfTime -> {
+            ids.add(pointOfTime.id(condition.getEntity().buildId()));
+        });
+
+        SearchResponse response = getClient().ids(condition.getName(), ids.toArray(new String[0]));
         Map<String, Map<String, Object>> idMap = toMap(response);
 
-        IntValues intValues = new IntValues();
+        MetricsValues metricsValues = new MetricsValues();
+        // Label is null, because in readMetricsValues, no label parameter.
+        IntValues intValues = metricsValues.getValues();
         for (String id : ids) {
             KVInt kvInt = new KVInt();
             kvInt.setId(id);
             kvInt.setValue(0);
             if (idMap.containsKey(id)) {
                 Map<String, Object> source = idMap.get(id);
-                kvInt.setValue(((Number) source.getOrDefault(valueCName, 0)).longValue());
+                kvInt.setValue(((Number) source.getOrDefault(valueColumnName, 0)).longValue());
+            } else {
+                kvInt.setValue(ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName()));
             }
             intValues.addKVInt(kvInt);
         }
 
-        return intValues;
+        metricsValues.setValues(
+            Util.sortValues(intValues, ids, ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName()))
+        );
+
+        return metricsValues;
     }
 
     @Override
-    public IntValues[] getMultipleLinearIntValues(String indexName, DownSampling downsampling, List<String> ids,
-                                                  List<Integer> linearIndex, String valueCName) throws IOException {
-        SearchResponse response = getClient().ids(indexName, ids.toArray(new String[0]));
+    public List<MetricsValues> readLabeledMetricsValues(final MetricsCondition condition,
+                                                        final String valueColumnName,
+                                                        final List<String> labels,
+                                                        final Duration duration) throws IOException {
+        final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
+        List<String> ids = new ArrayList<>(pointOfTimes.size());
+        pointOfTimes.forEach(pointOfTime -> {
+            ids.add(pointOfTime.id(condition.getEntity().buildId()));
+        });
+
+        SearchResponse response = getClient().ids(condition.getName(), ids.toArray(new String[0]));
         Map<String, Map<String, Object>> idMap = toMap(response);
 
-        IntValues[] intValuesArray = new IntValues[linearIndex.size()];
-        for (int i = 0; i < intValuesArray.length; i++) {
-            intValuesArray[i] = new IntValues();
-        }
+        Map<String, MetricsValues> labeledValues = new HashMap<>(labels.size());
+        labels.forEach(label -> {
+            MetricsValues labelValue = new MetricsValues();
+            labelValue.setLabel(label);
 
-        for (String id : ids) {
-            for (int i = 0; i < intValuesArray.length; i++) {
-                KVInt kvInt = new KVInt();
-                kvInt.setId(id);
-                kvInt.setValue(0);
-                intValuesArray[i].addKVInt(kvInt);
-            }
+            labeledValues.put(label, labelValue);
+        });
 
+        for (String id : ids) {
             if (idMap.containsKey(id)) {
                 Map<String, Object> source = idMap.get(id);
-                IntKeyLongValueHashMap multipleValues = new IntKeyLongValueHashMap(5);
-                multipleValues.toObject((String) source.getOrDefault(valueCName, ""));
-
-                for (int i = 0; i < linearIndex.size(); i++) {
-                    Integer index = linearIndex.get(i);
-                    intValuesArray[i].getLast().setValue(multipleValues.get(index).getValue());
-                }
+                DataTable multipleValues = new DataTable((String) source.getOrDefault(valueColumnName, ""));
+
+                labels.forEach(label -> {
+                    final Long data = multipleValues.get(label);
+                    final IntValues values = labeledValues.get(label).getValues();
+                    KVInt kv = new KVInt();
+                    kv.setId(id);
+                    kv.setValue(data);
+                    values.addKVInt(kv);
+                });
             }
 
         }
 
-        return intValuesArray;
+        return Util.sortValues(
+            new ArrayList<>(labeledValues.values()),
+            ids,
+            ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName())
+        );
     }
 
     @Override
-    public Thermodynamic getThermodynamic(String indexName, DownSampling downsampling, List<String> ids,
-                                          String valueCName) throws IOException {
-        Thermodynamic thermodynamic = new Thermodynamic();
-        List<List<Long>> thermodynamicValueMatrix = new ArrayList<>();
-
-        SearchResponse response = getClient().ids(indexName, ids.toArray(new String[0]));
+    public HeatMap readHeatMap(final MetricsCondition condition,
+                               final String valueColumnName,
+                               final Duration duration) throws IOException {
+        final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
+        List<String> ids = new ArrayList<>(pointOfTimes.size());
+        pointOfTimes.forEach(pointOfTime -> {
+            ids.add(pointOfTime.id(condition.getEntity().buildId()));
+        });
+
+        SearchResponse response = getClient().ids(condition.getName(), ids.toArray(new String[0]));
         Map<String, Map<String, Object>> idMap = toMap(response);
 
-        int numOfSteps = 0;
+        HeatMap heatMap = new HeatMap();
+
         for (String id : ids) {
             Map<String, Object> source = idMap.get(id);
-            if (source == null) {
-                // add empty list to represent no data exist for this time bucket
-                thermodynamicValueMatrix.add(new ArrayList<>());
-            } else {
-                int axisYStep = ((Number) source.get(ThermodynamicMetrics.STEP)).intValue();
-                thermodynamic.setAxisYStep(axisYStep);
-                numOfSteps = ((Number) source.get(ThermodynamicMetrics.NUM_OF_STEPS)).intValue() + 1;
-
-                String value = (String) source.get(ThermodynamicMetrics.DETAIL_GROUP);
-                IntKeyLongValueHashMap intKeyLongValues = new IntKeyLongValueHashMap(5);
-                intKeyLongValues.toObject(value);
+            if (source != null) {
+                String value = (String) source.get(HistogramMetrics.DATASET);
+                heatMap.buildColumn(id, value);
+            }
+        }
 
-                List<Long> axisYValues = new ArrayList<>();
-                for (int i = 0; i < numOfSteps; i++) {
-                    axisYValues.add(0L);
-                }
+        heatMap.fixMissingColumns(ids);
 
-                for (IntKeyLongValue intKeyLongValue : intKeyLongValues.values()) {
-                    axisYValues.set(intKeyLongValue.getKey(), intKeyLongValue.getValue());
-                }
+        return heatMap;
+    }
 
-                thermodynamicValueMatrix.add(axisYValues);
-            }
+    protected void functionAggregation(Function function, TermsAggregationBuilder parentAggBuilder, String valueCName) {
+        switch (function) {
+            case Avg:
+                parentAggBuilder.subAggregation(AggregationBuilders.avg(valueCName).field(valueCName));
+                break;
+            case Sum:
+                parentAggBuilder.subAggregation(AggregationBuilders.sum(valueCName).field(valueCName));
+                break;
+            default:
+                parentAggBuilder.subAggregation(AggregationBuilders.avg(valueCName).field(valueCName));
+                break;
         }
+    }
+
+    protected final void buildQuery(SearchSourceBuilder sourceBuilder, MetricsCondition condition, Duration duration) {
+        final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
+        List<String> ids = new ArrayList<>(pointOfTimes.size());
+        pointOfTimes.forEach(pointOfTime -> {
+            ids.add(pointOfTime.id(condition.getEntity().buildId()));
+        });
 
-        thermodynamic.fromMatrixData(thermodynamicValueMatrix, numOfSteps);
+        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(Metrics.TIME_BUCKET)
+                                                           .gte(duration.getStartTimeBucket())
+                                                           .lte(duration.getEndTimeBucket());
 
-        return thermodynamic;
+        final String entityId = condition.getEntity().buildId();
+
+        if (entityId == null) {
+            sourceBuilder.query(rangeQueryBuilder);
+        } else {
+            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
+            boolQuery.must().add(rangeQueryBuilder);
+            boolQuery.must().add(QueryBuilders.termsQuery(Metrics.ENTITY_ID, entityId));
+
+            sourceBuilder.query(boolQuery);
+        }
+        sourceBuilder.size(0);
     }
 
     private Map<String, Map<String, Object>> toMap(SearchResponse response) {
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileTaskLogEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileTaskLogEsDAO.java
index 0c7bf58..3e01098 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileTaskLogEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileTaskLogEsDAO.java
@@ -22,8 +22,8 @@ import java.io.IOException;
 import java.util.LinkedList;
 import java.util.List;
 import org.apache.skywalking.oap.server.core.profile.ProfileTaskLogRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLog;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLogOperationType;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLog;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLogOperationType;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileTaskQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileTaskQueryEsDAO.java
index cd376de..9368458 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileTaskQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileTaskQueryEsDAO.java
@@ -23,7 +23,7 @@ import java.util.LinkedList;
 import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.profile.ProfileTaskRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileThreadSnapshotQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileThreadSnapshotQueryEsDAO.java
index 09e0817..21f59e6 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileThreadSnapshotQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileThreadSnapshotQueryEsDAO.java
@@ -21,7 +21,7 @@ package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query;
 import com.google.common.base.Strings;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopNRecordsQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopNRecordsQueryEsDAO.java
index d859d01..7b324a7 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopNRecordsQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopNRecordsQueryEsDAO.java
@@ -21,9 +21,13 @@ package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import org.apache.skywalking.apm.util.StringUtil;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.analysis.topn.TopN;
-import org.apache.skywalking.oap.server.core.query.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNRecord;
+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.SelectedRecord;
 import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
@@ -40,24 +44,31 @@ public class TopNRecordsQueryEsDAO extends EsDAO implements ITopNRecordsQueryDAO
     }
 
     @Override
-    public List<TopNRecord> getTopNRecords(long startSecondTB, long endSecondTB, String metricName, String serviceId,
-        int topN, Order order) throws IOException {
+    public List<SelectedRecord> readSampledRecords(final TopNCondition condition,
+                                                   final Duration duration) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
         BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
-        boolQueryBuilder.must().add(QueryBuilders.rangeQuery(TopN.TIME_BUCKET).gte(startSecondTB).lte(endSecondTB));
-        boolQueryBuilder.must().add(QueryBuilders.termQuery(TopN.SERVICE_ID, serviceId));
+        boolQueryBuilder.must().add(QueryBuilders.rangeQuery(TopN.TIME_BUCKET)
+                                                 .gte(duration.getStartTimeBucket())
+                                                 .lte(duration.getEndTimeBucket()));
+
+        if (StringUtil.isNotEmpty(condition.getParentService())) {
+            final String serviceId = IDManager.ServiceID.buildId(condition.getParentService(), condition.isNormal());
+            boolQueryBuilder.must().add(QueryBuilders.termQuery(TopN.SERVICE_ID, serviceId));
+        }
 
         sourceBuilder.query(boolQueryBuilder);
-        sourceBuilder.size(topN).sort(TopN.LATENCY, order.equals(Order.DES) ? SortOrder.DESC : SortOrder.ASC);
-        SearchResponse response = getClient().search(metricName, sourceBuilder);
+        sourceBuilder.size(condition.getTopN())
+                     .sort(TopN.LATENCY, condition.getOrder().equals(Order.DES) ? SortOrder.DESC : SortOrder.ASC);
+        SearchResponse response = getClient().search(condition.getName(), sourceBuilder);
 
-        List<TopNRecord> results = new ArrayList<>();
+        List<SelectedRecord> results = new ArrayList<>(condition.getTopN());
 
         for (SearchHit searchHit : response.getHits().getHits()) {
-            TopNRecord record = new TopNRecord();
-            record.setStatement((String) searchHit.getSourceAsMap().get(TopN.STATEMENT));
-            record.setTraceId((String) searchHit.getSourceAsMap().get(TopN.TRACE_ID));
-            record.setLatency(((Number) searchHit.getSourceAsMap().get(TopN.LATENCY)).longValue());
+            SelectedRecord record = new SelectedRecord();
+            record.setName((String) searchHit.getSourceAsMap().get(TopN.STATEMENT));
+            record.setRefId((String) searchHit.getSourceAsMap().get(TopN.TRACE_ID));
+            record.setValue(((Number) searchHit.getSourceAsMap().get(TopN.LATENCY)).toString());
             results.add(record);
         }
 
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopologyQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopologyQueryEsDAO.java
index 8ed2d45..21fd086 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopologyQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopologyQueryEsDAO.java
@@ -22,14 +22,13 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.skywalking.oap.server.core.UnexpectedException;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.endpoint.EndpointRelationServerSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.instance.ServiceInstanceRelationClientSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.instance.ServiceInstanceRelationServerSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.service.ServiceRelationClientSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.service.ServiceRelationServerSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
-import org.apache.skywalking.oap.server.core.query.entity.Call;
+import org.apache.skywalking.oap.server.core.query.type.Call;
 import org.apache.skywalking.oap.server.core.source.DetectPoint;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
@@ -49,8 +48,7 @@ public class TopologyQueryEsDAO extends EsDAO implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(DownSampling downsampling,
-                                                                          long startTB,
+    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(long startTB,
                                                                           long endTB,
                                                                           List<String> serviceIds) throws IOException {
         if (CollectionUtils.isEmpty(serviceIds)) {
@@ -65,8 +63,7 @@ public class TopologyQueryEsDAO extends EsDAO implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(DownSampling downsampling,
-                                                                         long startTB,
+    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(long startTB,
                                                                          long endTB,
                                                                          List<String> serviceIds) throws IOException {
         if (CollectionUtils.isEmpty(serviceIds)) {
@@ -81,7 +78,7 @@ public class TopologyQueryEsDAO extends EsDAO implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(DownSampling downsampling, long startTB,
+    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(long startTB,
                                                                           long endTB) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
         sourceBuilder.query(QueryBuilders.rangeQuery(ServiceRelationServerSideMetrics.TIME_BUCKET)
@@ -93,7 +90,7 @@ public class TopologyQueryEsDAO extends EsDAO implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(DownSampling downsampling, long startTB,
+    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(long startTB,
                                                                          long endTB) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
         sourceBuilder.query(QueryBuilders.rangeQuery(ServiceRelationServerSideMetrics.TIME_BUCKET)
@@ -107,7 +104,6 @@ public class TopologyQueryEsDAO extends EsDAO implements ITopologyQueryDAO {
     @Override
     public List<Call.CallDetail> loadInstanceRelationDetectedAtServerSide(String clientServiceId,
                                                                           String serverServiceId,
-                                                                          DownSampling downsampling,
                                                                           long startTB,
                                                                           long endTB) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
@@ -121,7 +117,6 @@ public class TopologyQueryEsDAO extends EsDAO implements ITopologyQueryDAO {
     @Override
     public List<Call.CallDetail> loadInstanceRelationDetectedAtClientSide(String clientServiceId,
                                                                           String serverServiceId,
-                                                                          DownSampling downsampling,
                                                                           long startTB,
                                                                           long endTB) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
@@ -161,8 +156,7 @@ public class TopologyQueryEsDAO extends EsDAO implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadEndpointRelation(DownSampling downsampling,
-                                                      long startTB,
+    public List<Call.CallDetail> loadEndpointRelation(long startTB,
                                                       long endTB,
                                                       String destEndpointId) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TraceQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TraceQueryEsDAO.java
index 4617a73..192be91 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TraceQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TraceQueryEsDAO.java
@@ -26,11 +26,11 @@ import java.util.Collections;
 import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.Span;
-import org.apache.skywalking.oap.server.core.query.entity.TraceBrief;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.Span;
+import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AggregationQueryEs7DAO.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AggregationQueryEs7DAO.java
index 9b9e4e0..f5b9e37 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AggregationQueryEs7DAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AggregationQueryEs7DAO.java
@@ -18,61 +18,69 @@
 
 package org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
-import org.apache.skywalking.oap.server.core.query.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNEntity;
+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.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.AggregationQueryEsDAO;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.aggregations.AggregationBuilders;
 import org.elasticsearch.search.aggregations.BucketOrder;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
-import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
 import org.elasticsearch.search.aggregations.metrics.Avg;
 import org.elasticsearch.search.builder.SearchSourceBuilder;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
+/**
+ * {@link Avg} has package changes in ES 7, so have to rewrite the codes.
+ */
 public class AggregationQueryEs7DAO extends AggregationQueryEsDAO {
 
     public AggregationQueryEs7DAO(ElasticSearchClient client) {
         super(client);
     }
 
-    protected List<TopNEntity> aggregation(String indexName, String valueCName, SearchSourceBuilder sourceBuilder,
-        int topN, Order order) throws IOException {
+    @Override
+    public List<SelectedRecord> sortMetrics(final TopNCondition condition,
+                                            final String valueColumnName,
+                                            final Duration duration,
+                                            final List<KeyValue> additionalConditions) throws IOException {
+        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
+        sourceBuilder.query(QueryBuilders.rangeQuery(Metrics.TIME_BUCKET)
+                                         .lte(duration.getEndTimeBucket())
+                                         .gte(duration.getStartTimeBucket()));
 
         boolean asc = false;
-        if (order.equals(Order.ASC)) {
+        if (condition.getOrder().equals(Order.ASC)) {
             asc = true;
         }
 
-        TermsAggregationBuilder aggregationBuilder = aggregationBuilder(valueCName, topN, asc);
-
-        sourceBuilder.aggregation(aggregationBuilder);
+        sourceBuilder.aggregation(
+            AggregationBuilders.terms(Metrics.ENTITY_ID)
+                               .field(Metrics.ENTITY_ID)
+                               .order(BucketOrder.aggregation(valueColumnName, asc))
+                               .size(condition.getTopN())
+                               .subAggregation(AggregationBuilders.avg(valueColumnName).field(valueColumnName))
+        );
 
-        SearchResponse response = getClient().search(indexName, sourceBuilder);
+        SearchResponse response = getClient().search(condition.getName(), sourceBuilder);
 
-        List<TopNEntity> topNEntities = new ArrayList<>();
+        List<SelectedRecord> topNList = new ArrayList<>();
         Terms idTerms = response.getAggregations().get(Metrics.ENTITY_ID);
         for (Terms.Bucket termsBucket : idTerms.getBuckets()) {
-            TopNEntity topNEntity = new TopNEntity();
-            topNEntity.setId(termsBucket.getKeyAsString());
-            Avg value = termsBucket.getAggregations().get(valueCName);
-            topNEntity.setValue((long) value.getValue());
-            topNEntities.add(topNEntity);
+            SelectedRecord record = new SelectedRecord();
+            record.setId(termsBucket.getKeyAsString());
+            Avg value = termsBucket.getAggregations().get(valueColumnName);
+            record.setValue(String.valueOf((long) value.getValue()));
+            topNList.add(record);
         }
 
-        return topNEntities;
-    }
-
-    protected TermsAggregationBuilder aggregationBuilder(final String valueCName, final int topN, final boolean asc) {
-        return AggregationBuilders.terms(Metrics.ENTITY_ID)
-                                  .field(Metrics.ENTITY_ID)
-                                  .order(BucketOrder.aggregation(valueCName, asc))
-                                  .size(topN)
-                                  .subAggregation(AggregationBuilders.avg(valueCName).field(valueCName));
+        return topNList;
     }
 }
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AlarmQueryEs7DAO.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AlarmQueryEs7DAO.java
index aa7fad2..4d42e8f 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AlarmQueryEs7DAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AlarmQueryEs7DAO.java
@@ -20,9 +20,9 @@ package org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query;
 
 import com.google.common.base.Strings;
 import org.apache.skywalking.oap.server.core.alarm.AlarmRecord;
-import org.apache.skywalking.oap.server.core.query.entity.AlarmMessage;
-import org.apache.skywalking.oap.server.core.query.entity.Alarms;
-import org.apache.skywalking.oap.server.core.query.entity.Scope;
+import org.apache.skywalking.oap.server.core.query.type.AlarmMessage;
+import org.apache.skywalking.oap.server.core.query.type.Alarms;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
 import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/LogQueryEs7DAO.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/LogQueryEs7DAO.java
index 23a7ec6..c21d0da 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/LogQueryEs7DAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/LogQueryEs7DAO.java
@@ -25,11 +25,11 @@ import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.Const;
 import org.apache.skywalking.oap.server.core.analysis.manual.log.AbstractLogRecord;
 import org.apache.skywalking.oap.server.core.analysis.record.Record;
-import org.apache.skywalking.oap.server.core.query.entity.ContentType;
-import org.apache.skywalking.oap.server.core.query.entity.Log;
-import org.apache.skywalking.oap.server.core.query.entity.LogState;
-import org.apache.skywalking.oap.server.core.query.entity.Logs;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.ContentType;
+import org.apache.skywalking.oap.server.core.query.type.Log;
+import org.apache.skywalking.oap.server.core.query.type.LogState;
+import org.apache.skywalking.oap.server.core.query.type.Logs;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
 import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/MetadataQueryEs7DAO.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/MetadataQueryEs7DAO.java
index da0c278..89813d4 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/MetadataQueryEs7DAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/MetadataQueryEs7DAO.java
@@ -18,62 +18,12 @@
 
 package org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query;
 
-import java.io.IOException;
-import org.apache.skywalking.oap.server.core.analysis.NodeType;
-import org.apache.skywalking.oap.server.core.analysis.manual.endpoint.EndpointTraffic;
-import org.apache.skywalking.oap.server.core.analysis.manual.service.ServiceTraffic;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.MetadataQueryEsDAO;
-import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.index.query.BoolQueryBuilder;
-import org.elasticsearch.index.query.QueryBuilders;
-import org.elasticsearch.search.builder.SearchSourceBuilder;
 
 public class MetadataQueryEs7DAO extends MetadataQueryEsDAO {
 
     public MetadataQueryEs7DAO(final ElasticSearchClient client, final int queryMaxSize) {
         super(client, queryMaxSize);
     }
-
-    @Override
-    public int numOfService(long startTimestamp, long endTimestamp) throws IOException {
-        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-
-        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
-        boolQueryBuilder.must().add(QueryBuilders.termQuery(ServiceTraffic.NODE_TYPE, NodeType.Normal.value()));
-        sourceBuilder.query(boolQueryBuilder);
-        sourceBuilder.size(0);
-
-        SearchResponse response = getClient().search(ServiceTraffic.INDEX_NAME, sourceBuilder);
-        return (int) response.getHits().getTotalHits().value;
-    }
-
-    /**
-     * @since 7.0.0, as EndpointInventory has been replaced by EndpointTraffic. This is not an accurate number anymore.
-     */
-    @Override
-    public int numOfEndpoint() throws IOException {
-        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-
-        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
-
-        sourceBuilder.query(boolQueryBuilder);
-        sourceBuilder.size(0);
-
-        SearchResponse response = getClient().search(EndpointTraffic.INDEX_NAME, sourceBuilder);
-        return (int) response.getHits().getTotalHits().value;
-    }
-
-    @Override
-    public int numOfConjectural(int nodeTypeValue) throws IOException {
-        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-
-        sourceBuilder.query(QueryBuilders.termQuery(ServiceTraffic.NODE_TYPE, nodeTypeValue));
-        sourceBuilder.size(0);
-
-        SearchResponse response = getClient().search(ServiceTraffic.INDEX_NAME, sourceBuilder);
-
-        return (int) response.getHits().getTotalHits().value;
-    }
-
 }
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/MetricsQueryEs7DAO.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/MetricsQueryEs7DAO.java
index cdd5e1c..977c3e0 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/MetricsQueryEs7DAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/MetricsQueryEs7DAO.java
@@ -19,12 +19,11 @@
 package org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query;
 
 import java.io.IOException;
-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.entity.IntValues;
-import org.apache.skywalking.oap.server.core.query.entity.KVInt;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.MetricsCondition;
 import org.apache.skywalking.oap.server.core.query.sql.Function;
-import org.apache.skywalking.oap.server.core.query.sql.Where;
+import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.MetricsQueryEsDAO;
 import org.elasticsearch.action.search.SearchResponse;
@@ -35,6 +34,11 @@ import org.elasticsearch.search.aggregations.metrics.Avg;
 import org.elasticsearch.search.aggregations.metrics.Sum;
 import org.elasticsearch.search.builder.SearchSourceBuilder;
 
+/**
+ * Duplicate logic of {@link MetricsQueryEsDAO}, but for making compatible in ElasticSearch 7.
+ *
+ * {@link Avg} and {@link Sum} have different package in the es7.
+ */
 public class MetricsQueryEs7DAO extends MetricsQueryEsDAO {
 
     public MetricsQueryEs7DAO(ElasticSearchClient client) {
@@ -42,45 +46,37 @@ public class MetricsQueryEs7DAO extends MetricsQueryEsDAO {
     }
 
     @Override
-    public IntValues getValues(String indexName, DownSampling downsampling, long startTB, long endTB, Where where,
-                               String valueCName, Function function) throws IOException {
+    public int readMetricsValue(final MetricsCondition condition,
+                                final String valueColumnName,
+                                final Duration duration) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
-        queryBuild(sourceBuilder, where, startTB, endTB);
+        buildQuery(sourceBuilder, condition, duration);
 
         TermsAggregationBuilder entityIdAggregation = AggregationBuilders.terms(Metrics.ENTITY_ID)
                                                                          .field(Metrics.ENTITY_ID)
-                                                                         .size(1000);
-        functionAggregation(function, entityIdAggregation, valueCName);
+                                                                         .size(1);
+        final Function function = ValueColumnMetadata.INSTANCE.getValueFunction(condition.getName());
+        functionAggregation(function, entityIdAggregation, valueColumnName);
 
         sourceBuilder.aggregation(entityIdAggregation);
 
-        SearchResponse response = getClient().search(indexName, sourceBuilder);
+        SearchResponse response = getClient().search(condition.getName(), sourceBuilder);
 
-        IntValues intValues = new IntValues();
         Terms idTerms = response.getAggregations().get(Metrics.ENTITY_ID);
         for (Terms.Bucket idBucket : idTerms.getBuckets()) {
-            long value;
             switch (function) {
                 case Sum:
-                    Sum sum = idBucket.getAggregations().get(valueCName);
-                    value = (long) sum.getValue();
-                    break;
+                    Sum sum = idBucket.getAggregations().get(valueColumnName);
+                    return (int) sum.getValue();
                 case Avg:
-                    Avg avg = idBucket.getAggregations().get(valueCName);
-                    value = (long) avg.getValue();
-                    break;
+                    Avg avg = idBucket.getAggregations().get(valueColumnName);
+                    return (int) avg.getValue();
                 default:
-                    avg = idBucket.getAggregations().get(valueCName);
-                    value = (long) avg.getValue();
-                    break;
+                    avg = idBucket.getAggregations().get(valueColumnName);
+                    return (int) avg.getValue();
             }
-
-            KVInt kvInt = new KVInt();
-            kvInt.setId(idBucket.getKeyAsString());
-            kvInt.setValue(value);
-            intValues.addKVInt(kvInt);
         }
-        return intValues;
+        return ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName());
     }
 
     protected void functionAggregation(Function function, TermsAggregationBuilder parentAggBuilder, String valueCName) {
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/TraceQueryEs7DAO.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/TraceQueryEs7DAO.java
index 8bb97df..c78628d 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/TraceQueryEs7DAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/TraceQueryEs7DAO.java
@@ -23,10 +23,10 @@ import java.io.IOException;
 import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.TraceBrief;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.MatchCNameBuilder;
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/InfluxClient.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/InfluxClient.java
index fe96dd4..d12bd4c 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/InfluxClient.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/InfluxClient.java
@@ -24,7 +24,6 @@ import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.OkHttpClient;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
 import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
 import org.apache.skywalking.oap.server.library.client.Client;
 import org.apache.skywalking.oap.server.library.util.CollectionUtils;
@@ -196,13 +195,6 @@ public class InfluxClient implements Client {
     /**
      * Convert to InfluxDB {@link TimeInterval}.
      */
-    public static TimeInterval timeInterval(long timeBucket, DownSampling downsampling) {
-        return ti(TimeBucket.getTimestamp(timeBucket, downsampling), "ms");
-    }
-
-    /**
-     * Convert to InfluxDB {@link TimeInterval}.
-     */
     public static TimeInterval timeInterval(long timeBucket) {
         return ti(TimeBucket.getTimestamp(timeBucket), "ms");
     }
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/AggregationQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/AggregationQuery.java
index 48cd1ef..cdd94f4 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/AggregationQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/AggregationQuery.java
@@ -24,15 +24,18 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
-import org.apache.skywalking.oap.server.core.query.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNEntity;
+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.storage.query.IAggregationQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants;
 import org.influxdb.dto.QueryResult;
 import org.influxdb.querybuilder.SelectQueryImpl;
 import org.influxdb.querybuilder.SelectSubQueryImpl;
+import org.influxdb.querybuilder.WhereSubQueryImpl;
 
 import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.eq;
 import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.gte;
@@ -48,60 +51,38 @@ public class AggregationQuery implements IAggregationQueryDAO {
     }
 
     @Override
-    public List<TopNEntity> getServiceTopN(String indName, String valueCName, int topN, DownSampling downsampling,
-                                           long startTB, long endTB, Order order) throws IOException {
-        return getTopNEntity(downsampling, indName, subQuery(indName, valueCName, startTB, endTB), order, topN);
-    }
-
-    @Override
-    public List<TopNEntity> getAllServiceInstanceTopN(String indName, String valueCName, int topN,
-                                                      DownSampling downsampling,
-                                                      long startTB, long endTB, Order order) throws IOException {
-        return getTopNEntity(downsampling, indName, subQuery(indName, valueCName, startTB, endTB), order, topN);
-    }
-
-    @Override
-    public List<TopNEntity> getServiceInstanceTopN(String serviceId, String indName, String valueCName, int topN,
-                                                   DownSampling downsampling,
-                                                   long startTB, long endTB, Order order) throws IOException {
-        return getTopNEntity(
-            downsampling, indName,
-            subQuery(InfluxConstants.TagName.SERVICE_ID, serviceId, indName, valueCName, startTB, endTB), order, topN
-        );
-    }
-
-    @Override
-    public List<TopNEntity> getAllEndpointTopN(String indName, String valueCName, int topN, DownSampling downsampling,
-                                               long startTB, long endTB, Order order) throws IOException {
-        return getTopNEntity(downsampling, indName, subQuery(indName, valueCName, startTB, endTB), order, topN);
-    }
+    public List<SelectedRecord> sortMetrics(final TopNCondition condition,
+                                            final String valueColumnName,
+                                            final Duration duration,
+                                            final List<KeyValue> additionalConditions) throws IOException {
+        String measurement = condition.getName();
 
-    @Override
-    public List<TopNEntity> getEndpointTopN(String serviceId, String indName, String valueCName, int topN,
-                                            DownSampling downsampling,
-                                            long startTB, long endTB, Order order) throws IOException {
-        return getTopNEntity(
-            downsampling, indName,
-            subQuery(InfluxConstants.TagName.SERVICE_ID, serviceId, indName, valueCName, startTB, endTB), order, topN
-        );
-    }
-
-    private List<TopNEntity> getTopNEntity(DownSampling downsampling,
-                                           String measurement,
-                                           SelectSubQueryImpl<SelectQueryImpl> subQuery,
-                                           Order order,
-                                           int topN) throws IOException {
         // Have to re-sort here. Because the function, top()/bottom(), get the result ordered by the `time`.
-        Comparator<TopNEntity> comparator = DESCENDING;
+        Comparator<SelectedRecord> comparator = DESCENDING;
         String functionName = InfluxConstants.SORT_DES;
-        if (order == Order.ASC) {
+        if (condition.getOrder().equals(Order.ASC)) {
             functionName = InfluxConstants.SORT_ASC;
             comparator = ASCENDING;
         }
 
-        SelectQueryImpl query = select().function(functionName, "mean", topN).as("value")
+        SelectQueryImpl query = select().function(functionName, "mean", condition.getTopN()).as("value")
                                         .column(InfluxConstants.TagName.ENTITY_ID)
                                         .from(client.getDatabase(), measurement);
+
+        WhereSubQueryImpl<SelectSubQueryImpl<SelectQueryImpl>, SelectQueryImpl> where = select()
+            .fromSubQuery(client.getDatabase())
+            .mean(valueColumnName)
+            .from(condition.getName()).where();
+        if (additionalConditions != null) {
+            additionalConditions.forEach(moreCondition -> {
+                where.and(eq(moreCondition.getKey(), moreCondition.getValue()));
+            });
+        }
+        final SelectSubQueryImpl<SelectQueryImpl> subQuery = where
+            .and(gte(InfluxClient.TIME, InfluxClient.timeInterval(duration.getStartTimeBucket())))
+            .and(lte(InfluxClient.TIME, InfluxClient.timeInterval(duration.getEndTimeBucket())))
+            .groupBy(InfluxConstants.TagName.ENTITY_ID);
+
         query.setSubQuery(subQuery);
 
         List<QueryResult.Series> series = client.queryForSeries(query);
@@ -113,11 +94,11 @@ public class AggregationQuery implements IAggregationQueryDAO {
         }
 
         List<List<Object>> dataset = series.get(0).getValues();
-        List<TopNEntity> entities = Lists.newArrayListWithCapacity(dataset.size());
+        List<SelectedRecord> entities = Lists.newArrayListWithCapacity(dataset.size());
         dataset.forEach(values -> {
-            final TopNEntity entity = new TopNEntity();
+            final SelectedRecord entity = new SelectedRecord();
             entity.setId((String) values.get(2));
-            entity.setValue(((Double) values.get(1)).longValue());
+            entity.setValue(((Double) values.get(1)).longValue() + "");
             entities.add(entity);
         });
 
@@ -125,26 +106,9 @@ public class AggregationQuery implements IAggregationQueryDAO {
         return entities;
     }
 
-    private SelectSubQueryImpl<SelectQueryImpl> subQuery(String serviceColumnName, String serviceId, String name,
-                                                         String columnName,
-                                                         long startTB, long endTB) {
-        return select().fromSubQuery(client.getDatabase()).mean(columnName).from(name)
-                       .where()
-                       .and(eq(serviceColumnName, serviceId))
-                       .and(gte(InfluxClient.TIME, InfluxClient.timeInterval(startTB)))
-                       .and(lte(InfluxClient.TIME, InfluxClient.timeInterval(endTB)))
-                       .groupBy(InfluxConstants.TagName.ENTITY_ID);
-    }
-
-    private SelectSubQueryImpl<SelectQueryImpl> subQuery(String name, String columnName, long startTB, long endTB) {
-        return select().fromSubQuery(client.getDatabase()).mean(columnName).from(name)
-                       .where()
-                       .and(gte(InfluxClient.TIME, InfluxClient.timeInterval(startTB)))
-                       .and(lte(InfluxClient.TIME, InfluxClient.timeInterval(endTB)))
-                       .groupBy(InfluxConstants.TagName.ENTITY_ID);
-    }
-
-    private static final Comparator<TopNEntity> ASCENDING = Comparator.comparingLong(TopNEntity::getValue);
+    private static final Comparator<SelectedRecord> ASCENDING = (a, b) -> Long.compare(
+        Long.parseLong(a.getValue()), Long.parseLong(b.getValue()));
 
-    private static final Comparator<TopNEntity> DESCENDING = (a, b) -> Long.compare(b.getValue(), a.getValue());
+    private static final Comparator<SelectedRecord> DESCENDING = (a, b) -> Long.compare(
+        Long.parseLong(b.getValue()), Long.parseLong(a.getValue()));
 }
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/AlarmQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/AlarmQuery.java
index e964baf..e53f8e1 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/AlarmQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/AlarmQuery.java
@@ -23,9 +23,9 @@ import java.util.List;
 import java.util.Objects;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.oap.server.core.alarm.AlarmRecord;
-import org.apache.skywalking.oap.server.core.query.entity.AlarmMessage;
-import org.apache.skywalking.oap.server.core.query.entity.Alarms;
-import org.apache.skywalking.oap.server.core.query.entity.Scope;
+import org.apache.skywalking.oap.server.core.query.type.AlarmMessage;
+import org.apache.skywalking.oap.server.core.query.type.Alarms;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
 import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
 import org.elasticsearch.common.Strings;
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/LogQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/LogQuery.java
index 6b6019d..e47b7c3 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/LogQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/LogQuery.java
@@ -26,11 +26,11 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.Const;
 import org.apache.skywalking.oap.server.core.analysis.manual.log.AbstractLogRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ContentType;
-import org.apache.skywalking.oap.server.core.query.entity.Log;
-import org.apache.skywalking.oap.server.core.query.entity.LogState;
-import org.apache.skywalking.oap.server.core.query.entity.Logs;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.ContentType;
+import org.apache.skywalking.oap.server.core.query.type.Log;
+import org.apache.skywalking.oap.server.core.query.type.LogState;
+import org.apache.skywalking.oap.server.core.query.type.Logs;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
 import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.type.StorageDataComplexObject;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetadataQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetadataQuery.java
index bd04197..4c20e08 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetadataQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetadataQuery.java
@@ -35,13 +35,12 @@ import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
 import org.apache.skywalking.oap.server.core.analysis.manual.endpoint.EndpointTraffic;
 import org.apache.skywalking.oap.server.core.analysis.manual.instance.InstanceTraffic;
 import org.apache.skywalking.oap.server.core.analysis.manual.service.ServiceTraffic;
-import org.apache.skywalking.oap.server.core.query.entity.Attribute;
-import org.apache.skywalking.oap.server.core.query.entity.Database;
-import org.apache.skywalking.oap.server.core.query.entity.Endpoint;
-import org.apache.skywalking.oap.server.core.query.entity.Language;
-import org.apache.skywalking.oap.server.core.query.entity.LanguageTrans;
-import org.apache.skywalking.oap.server.core.query.entity.Service;
-import org.apache.skywalking.oap.server.core.query.entity.ServiceInstance;
+import org.apache.skywalking.oap.server.core.query.enumeration.Language;
+import org.apache.skywalking.oap.server.core.query.type.Attribute;
+import org.apache.skywalking.oap.server.core.query.type.Database;
+import org.apache.skywalking.oap.server.core.query.type.Endpoint;
+import org.apache.skywalking.oap.server.core.query.type.Service;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstance;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants;
@@ -70,36 +69,6 @@ public class MetadataQuery implements IMetadataQueryDAO {
     }
 
     @Override
-    public int numOfService(final long startTimestamp, final long endTimestamp) throws IOException {
-        WhereQueryImpl query = select().raw("count(distinct " + ID_COLUMN + ")")
-                                       .from(client.getDatabase(), ServiceTraffic.INDEX_NAME)
-                                       .where()
-                                       .and(
-                                           eq(InfluxConstants.TagName.NODE_TYPE, String.valueOf(NodeType.Normal.value())
-                                           ));
-        return client.getCounter(query);
-    }
-
-    @Override
-    public int numOfEndpoint() throws IOException {
-        SelectQueryImpl query = select()
-            .raw("count(distinct " + ID_COLUMN + ")")
-            .from(client.getDatabase(), EndpointTraffic.INDEX_NAME);
-        return client.getCounter(query);
-    }
-
-    @Override
-    public int numOfConjectural(final int nodeTypeValue) throws IOException {
-        WhereQueryImpl<SelectQueryImpl> query = select().raw("count(distinct " + ID_COLUMN + ")")
-                                                        .from(client.getDatabase(), ServiceTraffic.INDEX_NAME)
-                                                        .where(eq(
-                                                            InfluxConstants.TagName.NODE_TYPE,
-                                                            String.valueOf(nodeTypeValue)
-                                                        ));
-        return client.getCounter(query);
-    }
-
-    @Override
     public List<Service> getAllServices(final long startTimestamp, final long endTimestamp) throws IOException {
         SelectSubQueryImpl<SelectQueryImpl> subQuery = select()
             .fromSubQuery(client.getDatabase())
@@ -256,7 +225,7 @@ public class MetadataQuery implements IMetadataQueryDAO {
                     String key = property.getKey();
                     String value = property.getValue().getAsString();
                     if (key.equals(InstanceTraffic.PropertyUtil.LANGUAGE)) {
-                        serviceInstance.setLanguage(LanguageTrans.INSTANCE.value(value));
+                        serviceInstance.setLanguage(Language.value(value));
                     } else {
                         serviceInstance.getAttributes().add(new Attribute(key, value));
                     }
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetricsQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetricsQuery.java
index a28f1c6..60cde6a 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetricsQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/MetricsQuery.java
@@ -19,29 +19,26 @@
 package org.apache.skywalking.oap.server.storage.plugin.influxdb.query;
 
 import com.google.common.base.Joiner;
-import com.google.common.collect.Maps;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValue;
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValueHashMap;
-import org.apache.skywalking.oap.server.core.analysis.metrics.ThermodynamicMetrics;
-import org.apache.skywalking.oap.server.core.query.entity.IntValues;
-import org.apache.skywalking.oap.server.core.query.entity.KVInt;
-import org.apache.skywalking.oap.server.core.query.entity.Thermodynamic;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
+import org.apache.skywalking.oap.server.core.query.PointOfTime;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.MetricsCondition;
 import org.apache.skywalking.oap.server.core.query.sql.Function;
-import org.apache.skywalking.oap.server.core.query.sql.KeyValues;
-import org.apache.skywalking.oap.server.core.query.sql.Where;
-import org.apache.skywalking.oap.server.core.storage.model.ModelColumn;
+import org.apache.skywalking.oap.server.core.query.type.HeatMap;
+import org.apache.skywalking.oap.server.core.query.type.IntValues;
+import org.apache.skywalking.oap.server.core.query.type.KVInt;
+import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
+import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
 import org.apache.skywalking.oap.server.library.util.CollectionUtils;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants;
-import org.apache.skywalking.oap.server.storage.plugin.influxdb.TableMetaInfo;
 import org.influxdb.dto.QueryResult;
 import org.influxdb.querybuilder.SelectQueryImpl;
 import org.influxdb.querybuilder.SelectionQueryImpl;
@@ -63,87 +60,60 @@ public class MetricsQuery implements IMetricsQueryDAO {
     }
 
     @Override
-    public IntValues getValues(String measurement, DownSampling downsampling, long startTB, long endTB,
-                               Where where, String valueCName, Function function) throws IOException {
+    public int readMetricsValue(final MetricsCondition condition,
+                                final String valueColumnName,
+                                final Duration duration) throws IOException {
+        final Function function = ValueColumnMetadata.INSTANCE.getValueFunction(condition.getName());
+        final String measurement = condition.getName();
+
         SelectionQueryImpl query = select();
         switch (function) {
             case Avg:
-                query.mean(valueCName);
+                query.mean(valueColumnName);
                 break;
             default:
-                query.sum(valueCName);
+                query.sum(valueColumnName);
         }
         WhereQueryImpl<SelectQueryImpl> queryWhereQuery = query.from(client.getDatabase(), measurement).where();
 
-        Map<String, Class<?>> columnTypes = Maps.newHashMap();
-        for (ModelColumn column : TableMetaInfo.get(measurement).getModel().getColumns()) {
-            columnTypes.put(column.getColumnName().getStorageName(), column.getType());
+        final String entityId = condition.getEntity().buildId();
+        if (entityId != null) {
+            queryWhereQuery.and(eq(InfluxConstants.TagName.ENTITY_ID, entityId));
         }
 
-        List<String> ids = new ArrayList<>(20);
-        List<KeyValues> whereKeyValues = where.getKeyValues();
-        if (!whereKeyValues.isEmpty()) {
-            StringBuilder clauseBuilder = new StringBuilder();
-            for (KeyValues kv : whereKeyValues) {
-                final List<String> values = kv.getValues();
-                ids.addAll(values);
-
-                Class<?> type = columnTypes.get(kv.getKey());
-                if (values.size() == 1) {
-                    String value = kv.getValues().get(0);
-                    if (type == String.class) {
-                        value = "'" + value + "'";
-                    }
-                    clauseBuilder.append(kv.getKey()).append("=").append(value).append(" OR ");
-                } else {
-                    if (type == String.class) {
-                        clauseBuilder.append(kv.getKey())
-                                     .append(" =~ /")
-                                     .append(Joiner.on("|").join(values))
-                                     .append("/ OR ");
-                    } else {
-                        for (String value : values) {
-                            clauseBuilder.append(kv.getKey()).append(" = '").append(value).append("' OR ");
-                        }
-                    }
-                }
-            }
-            queryWhereQuery.where(clauseBuilder.substring(0, clauseBuilder.length() - 4));
-        }
         queryWhereQuery
-            .and(gte(InfluxClient.TIME, InfluxClient.timeInterval(startTB, downsampling)))
-            .and(lte(InfluxClient.TIME, InfluxClient.timeInterval(endTB, downsampling)))
+            .and(gte(InfluxClient.TIME, InfluxClient.timeInterval(duration.getStartTimeBucket())))
+            .and(lte(InfluxClient.TIME, InfluxClient.timeInterval(duration.getEndTimeBucket())))
             .groupBy(InfluxConstants.TagName.ENTITY_ID);
 
-        IntValues intValues = new IntValues();
         List<QueryResult.Series> seriesList = client.queryForSeries(queryWhereQuery);
         if (log.isDebugEnabled()) {
             log.debug("SQL: {} result set: {}", queryWhereQuery.getCommand(), seriesList);
         }
         if (CollectionUtils.isNotEmpty(seriesList)) {
             for (QueryResult.Series series : seriesList) {
-                KVInt kv = new KVInt();
-                kv.setId(series.getTags().get(InfluxConstants.TagName.ENTITY_ID));
                 Number value = (Number) series.getValues().get(0).get(1);
-                kv.setValue(value.longValue());
-
-                intValues.addKVInt(kv);
+                return value.intValue();
             }
         }
 
-        return orderWithDefault0(intValues, ids);
+        return ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName());
     }
 
     @Override
-    public IntValues getLinearIntValues(String measurement,
-                                        DownSampling downsampling,
-                                        List<String> ids,
-                                        String valueCName)
-        throws IOException {
+    public MetricsValues readMetricsValues(final MetricsCondition condition,
+                                           final String valueColumnName,
+                                           final Duration duration) throws IOException {
+        final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
+        List<String> ids = new ArrayList<>(pointOfTimes.size());
+        pointOfTimes.forEach(pointOfTime -> {
+            ids.add(pointOfTime.id(condition.getEntity().buildId()));
+        });
+
         WhereQueryImpl<SelectQueryImpl> query = select()
             .column(ID_COLUMN)
-            .column(valueCName)
-            .from(client.getDatabase(), measurement)
+            .column(valueColumnName)
+            .from(client.getDatabase(), condition.getName())
             .where();
 
         if (CollectionUtils.isNotEmpty(ids)) {
@@ -158,7 +128,10 @@ public class MetricsQuery implements IMetricsQueryDAO {
             log.debug("SQL: {} result set: {}", query.getCommand(), seriesList);
         }
 
-        IntValues intValues = new IntValues();
+        MetricsValues metricsValues = new MetricsValues();
+        // Label is null, because in readMetricsValues, no label parameter.
+        final IntValues intValues = metricsValues.getValues();
+
         if (CollectionUtils.isNotEmpty(seriesList)) {
             seriesList.get(0).getValues().forEach(values -> {
                 KVInt kv = new KVInt();
@@ -167,96 +140,87 @@ public class MetricsQuery implements IMetricsQueryDAO {
                 intValues.addKVInt(kv);
             });
         }
-        return orderWithDefault0(intValues, ids);
+        metricsValues.setValues(
+            Util.sortValues(intValues, ids, ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName()))
+        );
+        return metricsValues;
     }
 
-    /**
-     * Make sure the order is same as the expected order, and keep default value as 0.
-     *
-     * @param origin        IntValues
-     * @param expectedOrder List
-     * @return
-     */
-    private IntValues orderWithDefault0(IntValues origin, List<String> expectedOrder) {
-        IntValues intValues = new IntValues();
-
-        expectedOrder.forEach(id -> {
-            KVInt e = new KVInt();
-            e.setId(id);
-            e.setValue(origin.findValue(id, 0));
-            intValues.addKVInt(e);
+    @Override
+    public List<MetricsValues> readLabeledMetricsValues(final MetricsCondition condition,
+                                                        final String valueColumnName,
+                                                        final List<String> labels,
+                                                        final Duration duration) throws IOException {
+        final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
+        List<String> ids = new ArrayList<>(pointOfTimes.size());
+        pointOfTimes.forEach(pointOfTime -> {
+            ids.add(pointOfTime.id(condition.getEntity().buildId()));
         });
 
-        return intValues;
-    }
-
-    @Override
-    public IntValues[] getMultipleLinearIntValues(String measurement, DownSampling downsampling, List<String> ids,
-                                                  List<Integer> linearIndex, String valueCName) throws IOException {
         WhereQueryImpl<SelectQueryImpl> query = select()
-            .column("id")
-            .column(valueCName)
-            .from(client.getDatabase(), measurement)
+            .column(ID_COLUMN)
+            .column(valueColumnName)
+            .from(client.getDatabase(), condition.getName())
             .where();
 
         if (CollectionUtils.isNotEmpty(ids)) {
             if (ids.size() == 1) {
-                query.where(eq("id", ids.get(0)));
+                query.where(eq(ID_COLUMN, ids.get(0)));
             } else {
-                query.where(contains("id", Joiner.on("|").join(ids)));
+                query.where(contains(ID_COLUMN, Joiner.on("|").join(ids)));
             }
         }
         List<QueryResult.Series> series = client.queryForSeries(query);
         if (log.isDebugEnabled()) {
             log.debug("SQL: {} result set: {}", query.getCommand(), series);
         }
-        IntValues[] intValues = new IntValues[linearIndex.size()];
-        for (int i = 0; i < intValues.length; i++) {
-            intValues[i] = new IntValues();
-        }
-        if (CollectionUtils.isEmpty(series)) {
-            return intValues;
-        }
-        series.get(0).getValues().forEach(values -> {
-            IntKeyLongValueHashMap multipleValues = new IntKeyLongValueHashMap(5);
-            multipleValues.toObject((String) values.get(2));
 
-            final String id = (String) values.get(1);
-            for (int i = 0; i < intValues.length; i++) {
-                Integer index = linearIndex.get(i);
-                KVInt kv = new KVInt();
-                kv.setId(id);
-                kv.setValue(multipleValues.get(index).getValue());
-                intValues[i].addKVInt(kv);
-            }
+        Map<String, MetricsValues> labeledValues = new HashMap<>(labels.size());
+        labels.forEach(label -> {
+            MetricsValues labelValue = new MetricsValues();
+            labelValue.setLabel(label);
+
+            labeledValues.put(label, labelValue);
         });
-        return orderWithDefault0(intValues, ids);
-    }
 
-    /**
-     * Make sure the order is same as the expected order, and keep default value as 0.
-     *
-     * @param origin        IntValues[]
-     * @param expectedOrder List
-     * @return
-     */
-    private IntValues[] orderWithDefault0(IntValues[] origin, List<String> expectedOrder) {
-        for (int i = 0; i < origin.length; i++) {
-            origin[i] = orderWithDefault0(origin[i], expectedOrder);
+        if (!CollectionUtils.isEmpty(series)) {
+            series.get(0).getValues().forEach(values -> {
+                final String id = (String) values.get(1);
+                DataTable multipleValues = new DataTable(5);
+                multipleValues.toObject((String) values.get(2));
+
+                labels.forEach(label -> {
+                    final Long data = multipleValues.get(label);
+                    final IntValues intValues = labeledValues.get(label).getValues();
+                    KVInt kv = new KVInt();
+                    kv.setId(id);
+                    kv.setValue(data);
+                    intValues.addKVInt(kv);
+                });
+            });
         }
-        return origin;
+
+        return Util.sortValues(
+            new ArrayList<>(labeledValues.values()),
+            ids,
+            ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName())
+        );
     }
 
     @Override
-    public Thermodynamic getThermodynamic(String measurement, DownSampling downsampling, List<String> ids,
-                                          String valueCName)
-        throws IOException {
+    public HeatMap readHeatMap(final MetricsCondition condition,
+                               final String valueColumnName,
+                               final Duration duration) throws IOException {
+        final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
+        List<String> ids = new ArrayList<>(pointOfTimes.size());
+        pointOfTimes.forEach(pointOfTime -> {
+            ids.add(pointOfTime.id(condition.getEntity().buildId()));
+        });
+
         WhereQueryImpl<SelectQueryImpl> query = select()
-            .column(ThermodynamicMetrics.STEP)
-            .column(ThermodynamicMetrics.NUM_OF_STEPS)
-            .column(ThermodynamicMetrics.DETAIL_GROUP)
             .column(ID_COLUMN)
-            .from(client.getDatabase(), measurement)
+            .column(valueColumnName)
+            .from(client.getDatabase(), condition.getName())
             .where(contains(ID_COLUMN, Joiner.on("|").join(ids)));
         Map<String, List<Long>> thermodynamicValueMatrix = new HashMap<>();
 
@@ -264,38 +228,16 @@ public class MetricsQuery implements IMetricsQueryDAO {
         if (log.isDebugEnabled()) {
             log.debug("SQL: {} result set: {}", query.getCommand(), series);
         }
-        if (series == null) {
-            return new Thermodynamic();
-        }
 
-        int numOfSteps = 0, axisYStep = 0;
-        List<List<Long>> thermodynamicValueCollection = new ArrayList<>();
-        Thermodynamic thermodynamic = new Thermodynamic();
-        for (List<Object> values : series.getValues()) {
-            numOfSteps = (int) values.get(2) + 1;
-            axisYStep = (int) values.get(1);
-            IntKeyLongValueHashMap intKeyLongValues = new IntKeyLongValueHashMap(5);
-            intKeyLongValues.toObject((String) values.get(3));
-            List<Long> axisYValues = new ArrayList<>(numOfSteps);
-            for (int i = 0; i < numOfSteps; i++) {
-                axisYValues.add(0L);
-            }
-            for (IntKeyLongValue intKeyLongValue : intKeyLongValues.values()) {
-                axisYValues.set(intKeyLongValue.getKey(), intKeyLongValue.getValue());
+        HeatMap heatMap = new HeatMap();
+        if (series != null) {
+            for (List<Object> values : series.getValues()) {
+                heatMap.buildColumn(values.get(1).toString(), values.get(2).toString());
             }
-            thermodynamicValueMatrix.put((String) values.get(4), axisYValues);
         }
-        // try to add default values when there is no data in that time bucket.
-        ids.forEach(id -> {
-            if (thermodynamicValueMatrix.containsKey(id)) {
-                thermodynamicValueCollection.add(thermodynamicValueMatrix.get(id));
-            } else {
-                thermodynamicValueCollection.add(new ArrayList<>());
-            }
-        });
-        thermodynamic.fromMatrixData(thermodynamicValueCollection, numOfSteps);
-        thermodynamic.setAxisYStep(axisYStep);
 
-        return thermodynamic;
+        heatMap.fixMissingColumns(ids);
+
+        return heatMap;
     }
 }
\ No newline at end of file
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileTaskLogQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileTaskLogQuery.java
index 59982d8..2fb972c 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileTaskLogQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileTaskLogQuery.java
@@ -24,8 +24,8 @@ import java.util.Collections;
 import java.util.List;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.oap.server.core.profile.ProfileTaskLogRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLog;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLogOperationType;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLog;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLogOperationType;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants;
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileTaskQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileTaskQuery.java
index 43099ef..701d705 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileTaskQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileTaskQuery.java
@@ -25,7 +25,7 @@ import java.util.Objects;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.profile.ProfileTaskRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants;
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileThreadSnapshotQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileThreadSnapshotQuery.java
index 25dfc0e..2e3f2ed 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileThreadSnapshotQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/ProfileThreadSnapshotQuery.java
@@ -31,7 +31,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TopNRecordsQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TopNRecordsQuery.java
index 1dda92c..ba7a592 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TopNRecordsQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TopNRecordsQuery.java
@@ -25,9 +25,12 @@ import java.util.Comparator;
 import java.util.List;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.apm.util.StringUtil;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.analysis.topn.TopN;
-import org.apache.skywalking.oap.server.core.query.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNRecord;
+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.SelectedRecord;
 import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants;
@@ -48,26 +51,27 @@ public class TopNRecordsQuery implements ITopNRecordsQueryDAO {
     }
 
     @Override
-    public List<TopNRecord> getTopNRecords(long startSecondTB, long endSecondTB, String metricName,
-                                           String serviceId, int topN, Order order) throws IOException {
+    public List<SelectedRecord> readSampledRecords(final TopNCondition condition,
+                                                   final Duration duration) throws IOException {
         String function = InfluxConstants.SORT_ASC;
         // Have to re-sort here. Because the function, top()/bottom(), get the result ordered by the `time`.
-        Comparator<TopNRecord> comparator = Comparator.comparingLong(TopNRecord::getLatency);
-        if (order.equals(Order.DES)) {
+        Comparator<SelectedRecord> comparator = ASCENDING;
+        if (condition.getOrder().equals(Order.DES)) {
             function = InfluxConstants.SORT_DES;
-            comparator = (a, b) -> Long.compare(b.getLatency(), a.getLatency());
+            comparator = DESCENDING;
         }
 
         WhereQueryImpl query = select()
-            .function(function, TopN.LATENCY, topN)
+            .function(function, TopN.LATENCY, condition.getTopN())
             .column(TopN.STATEMENT)
             .column(TopN.TRACE_ID)
-            .from(client.getDatabase(), metricName)
+            .from(client.getDatabase(), condition.getName())
             .where()
-            .and(gte(TopN.TIME_BUCKET, startSecondTB))
-            .and(lte(TopN.TIME_BUCKET, endSecondTB));
+            .and(gte(TopN.TIME_BUCKET, duration.getStartTimeBucket()))
+            .and(lte(TopN.TIME_BUCKET, duration.getEndTimeBucket()));
 
-        if (StringUtil.isNotEmpty(serviceId)) {
+        if (StringUtil.isNotEmpty(condition.getParentService())) {
+            final String serviceId = IDManager.ServiceID.buildId(condition.getParentService(), condition.isNormal());
             query.and(eq(InfluxConstants.TagName.SERVICE_ID, serviceId));
         }
 
@@ -79,16 +83,22 @@ public class TopNRecordsQuery implements ITopNRecordsQueryDAO {
             return Collections.emptyList();
         }
 
-        final List<TopNRecord> records = new ArrayList<>();
+        final List<SelectedRecord> records = new ArrayList<>();
         series.getValues().forEach(values -> {
-            TopNRecord record = new TopNRecord();
-            record.setLatency((long) values.get(1));
-            record.setTraceId((String) values.get(3));
-            record.setStatement((String) values.get(2));
+            SelectedRecord record = new SelectedRecord();
+            record.setValue(String.valueOf((long) values.get(1)));
+            record.setRefId((String) values.get(3));
+            record.setName((String) values.get(2));
             records.add(record);
         });
 
         Collections.sort(records, comparator); // re-sort by self, because of the result order by time.
         return records;
     }
+
+    private static final Comparator<SelectedRecord> ASCENDING = (a, b) -> Long.compare(
+        Long.parseLong(a.getValue()), Long.parseLong(b.getValue()));
+
+    private static final Comparator<SelectedRecord> DESCENDING = (a, b) -> Long.compare(
+        Long.parseLong(b.getValue()), Long.parseLong(a.getValue()));
 }
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TopologyQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TopologyQuery.java
index 67b6f4a..d659de3 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TopologyQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TopologyQuery.java
@@ -23,13 +23,12 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.endpoint.EndpointRelationServerSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.instance.ServiceInstanceRelationClientSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.instance.ServiceInstanceRelationServerSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.service.ServiceRelationClientSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.service.ServiceRelationServerSideMetrics;
-import org.apache.skywalking.oap.server.core.query.entity.Call;
+import org.apache.skywalking.oap.server.core.query.type.Call;
 import org.apache.skywalking.oap.server.core.source.DetectPoint;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
@@ -55,7 +54,7 @@ public class TopologyQuery implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(DownSampling downsampling, long startTB,
+    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(long startTB,
                                                                           long endTB,
                                                                           List<String> serviceIds) throws IOException {
         String measurement = ServiceRelationServerSideMetrics.INDEX_NAME;
@@ -72,7 +71,7 @@ public class TopologyQuery implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(DownSampling downsampling, long startTB,
+    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(long startTB,
                                                                          long endTB,
                                                                          List<String> serviceIds) throws IOException {
         String measurement = ServiceRelationClientSideMetrics.INDEX_NAME;
@@ -88,7 +87,7 @@ public class TopologyQuery implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(DownSampling downsampling, long startTB,
+    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(long startTB,
                                                                           long endTB) throws IOException {
         String measurement = ServiceRelationServerSideMetrics.INDEX_NAME;
         WhereSubQueryImpl<SelectSubQueryImpl<SelectQueryImpl>, SelectQueryImpl> subQuery = buildServiceCallsQuery(
@@ -103,7 +102,7 @@ public class TopologyQuery implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(DownSampling downsampling, long startTB,
+    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(long startTB,
                                                                          long endTB) throws IOException {
         String tableName = ServiceRelationClientSideMetrics.INDEX_NAME;
         WhereSubQueryImpl<SelectSubQueryImpl<SelectQueryImpl>, SelectQueryImpl> subQuery = buildServiceCallsQuery(
@@ -120,7 +119,6 @@ public class TopologyQuery implements ITopologyQueryDAO {
     @Override
     public List<Call.CallDetail> loadInstanceRelationDetectedAtServerSide(String clientServiceId,
                                                                           String serverServiceId,
-                                                                          DownSampling downsampling,
                                                                           long startTB,
                                                                           long endTB) throws IOException {
         String measurement = ServiceInstanceRelationServerSideMetrics.INDEX_NAME;
@@ -138,7 +136,6 @@ public class TopologyQuery implements ITopologyQueryDAO {
     @Override
     public List<Call.CallDetail> loadInstanceRelationDetectedAtClientSide(String clientServiceId,
                                                                           String serverServiceId,
-                                                                          DownSampling downsampling,
                                                                           long startTB,
                                                                           long endTB) throws IOException {
         String measurement = ServiceInstanceRelationClientSideMetrics.INDEX_NAME;
@@ -154,8 +151,7 @@ public class TopologyQuery implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadEndpointRelation(DownSampling downsampling,
-                                                      long startTB,
+    public List<Call.CallDetail> loadEndpointRelation(long startTB,
                                                       long endTB,
                                                       String destEndpointId) throws IOException {
         String measurement = EndpointRelationServerSideMetrics.INDEX_NAME;
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TraceQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TraceQuery.java
index 9e577fa..2b8b7c7 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TraceQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TraceQuery.java
@@ -26,11 +26,11 @@ import java.util.List;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.Span;
-import org.apache.skywalking.oap.server.core.query.entity.TraceBrief;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.Span;
+import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
 import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
diff --git a/oap-server/server-storage-plugin/storage-jaeger-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jaeger/elasticsearch/JaegerTraceQueryEsDAO.java b/oap-server/server-storage-plugin/storage-jaeger-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jaeger/elasticsearch/JaegerTraceQueryEsDAO.java
index 92c7f61..6bcd4af 100644
--- a/oap-server/server-storage-plugin/storage-jaeger-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jaeger/elasticsearch/JaegerTraceQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-jaeger-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jaeger/elasticsearch/JaegerTraceQueryEsDAO.java
@@ -30,15 +30,15 @@ import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
-import org.apache.skywalking.oap.server.core.query.entity.KeyValue;
-import org.apache.skywalking.oap.server.core.query.entity.LogEntity;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.Ref;
-import org.apache.skywalking.oap.server.core.query.entity.RefType;
-import org.apache.skywalking.oap.server.core.query.entity.Span;
-import org.apache.skywalking.oap.server.core.query.entity.TraceBrief;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.KeyValue;
+import org.apache.skywalking.oap.server.core.query.type.LogEntity;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.Ref;
+import org.apache.skywalking.oap.server.core.query.type.RefType;
+import org.apache.skywalking.oap.server.core.query.type.Span;
+import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
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 eef55f4..6de3579 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
@@ -26,12 +26,12 @@ import java.util.ArrayList;
 import java.util.List;
 import lombok.AccessLevel;
 import lombok.Getter;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
-import org.apache.skywalking.oap.server.core.analysis.manual.endpoint.EndpointTraffic;
-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.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNEntity;
+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.storage.query.IAggregationQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
 
@@ -45,89 +45,41 @@ 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);
+        sql.append(Metrics.TIME_BUCKET).append(" >= ? and ").append(Metrics.TIME_BUCKET).append(" <= ?");
+        conditions.add(duration.getStartTimeBucket());
+        conditions.add(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) {
@@ -135,15 +87,4 @@ public class H2AggregationQueryDAO implements IAggregationQueryDAO {
         }
         return topNEntities;
     }
-
-    protected void setTimeRangeCondition(StringBuilder sql, List<Object> conditions, long startTimestamp,
-                                         long endTimestamp) {
-        sql.append(Metrics.TIME_BUCKET).append(" >= ? and ").append(Metrics.TIME_BUCKET).append(" <= ?");
-        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/h2/dao/H2AlarmQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AlarmQueryDAO.java
index e5315cf..0f4ff85 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AlarmQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AlarmQueryDAO.java
@@ -19,9 +19,9 @@
 package org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao;
 
 import org.apache.skywalking.oap.server.core.alarm.AlarmRecord;
-import org.apache.skywalking.oap.server.core.query.entity.AlarmMessage;
-import org.apache.skywalking.oap.server.core.query.entity.Alarms;
-import org.apache.skywalking.oap.server.core.query.entity.Scope;
+import org.apache.skywalking.oap.server.core.query.type.AlarmMessage;
+import org.apache.skywalking.oap.server.core.query.type.Alarms;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
 import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
 import org.elasticsearch.common.Strings;
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/H2LogQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2LogQueryDAO.java
index cc1fabb..ef6f922 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2LogQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2LogQueryDAO.java
@@ -28,11 +28,11 @@ import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.Const;
 import org.apache.skywalking.oap.server.core.analysis.manual.log.AbstractLogRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ContentType;
-import org.apache.skywalking.oap.server.core.query.entity.Log;
-import org.apache.skywalking.oap.server.core.query.entity.LogState;
-import org.apache.skywalking.oap.server.core.query.entity.Logs;
-import org.apache.skywalking.oap.server.core.query.entity.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.ContentType;
+import org.apache.skywalking.oap.server.core.query.type.Log;
+import org.apache.skywalking.oap.server.core.query.type.LogState;
+import org.apache.skywalking.oap.server.core.query.type.Logs;
+import org.apache.skywalking.oap.server.core.query.type.Pagination;
 import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
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/H2MetadataQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2MetadataQueryDAO.java
index 0be9779..2566ab2 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2MetadataQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2MetadataQueryDAO.java
@@ -34,13 +34,12 @@ import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
 import org.apache.skywalking.oap.server.core.analysis.manual.endpoint.EndpointTraffic;
 import org.apache.skywalking.oap.server.core.analysis.manual.instance.InstanceTraffic;
 import org.apache.skywalking.oap.server.core.analysis.manual.service.ServiceTraffic;
-import org.apache.skywalking.oap.server.core.query.entity.Attribute;
-import org.apache.skywalking.oap.server.core.query.entity.Database;
-import org.apache.skywalking.oap.server.core.query.entity.Endpoint;
-import org.apache.skywalking.oap.server.core.query.entity.Language;
-import org.apache.skywalking.oap.server.core.query.entity.LanguageTrans;
-import org.apache.skywalking.oap.server.core.query.entity.Service;
-import org.apache.skywalking.oap.server.core.query.entity.ServiceInstance;
+import org.apache.skywalking.oap.server.core.query.enumeration.Language;
+import org.apache.skywalking.oap.server.core.query.type.Attribute;
+import org.apache.skywalking.oap.server.core.query.type.Database;
+import org.apache.skywalking.oap.server.core.query.type.Endpoint;
+import org.apache.skywalking.oap.server.core.query.type.Service;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstance;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
 
@@ -56,50 +55,6 @@ public class H2MetadataQueryDAO implements IMetadataQueryDAO {
     }
 
     @Override
-    public int numOfService(long startTimestamp, long endTimestamp) throws IOException {
-        StringBuilder sql = new StringBuilder();
-        List<Object> condition = new ArrayList<>(5);
-        sql.append("select count(1) num from ").append(ServiceTraffic.INDEX_NAME).append(" where ");
-        sql.append(ServiceTraffic.NODE_TYPE).append("=" + NodeType.Normal.value());
-
-        return getNum(sql, condition);
-    }
-
-    private Integer getNum(StringBuilder sql, List<Object> condition) throws IOException {
-        try (Connection connection = h2Client.getConnection()) {
-            try (ResultSet resultSet = h2Client.executeQuery(
-                connection, sql.toString(), condition.toArray(new Object[0]))) {
-                if (resultSet.next()) {
-                    return resultSet.getInt("num");
-                }
-            }
-        } catch (SQLException e) {
-            throw new IOException(e);
-        }
-        return 0;
-    }
-
-    @Override
-    public int numOfEndpoint() throws IOException {
-        StringBuilder sql = new StringBuilder();
-        List<Object> condition = new ArrayList<>(5);
-        sql.append("select count(*) num from ").append(EndpointTraffic.INDEX_NAME);
-
-        return getNum(sql, condition);
-    }
-
-    @Override
-    public int numOfConjectural(int nodeTypeValue) throws IOException {
-        StringBuilder sql = new StringBuilder();
-        List<Object> condition = new ArrayList<>(5);
-        sql.append("select count(*) num from ").append(ServiceTraffic.INDEX_NAME).append(" where ");
-        sql.append(ServiceTraffic.NODE_TYPE).append("=?");
-        condition.add(nodeTypeValue);
-
-        return getNum(sql, condition);
-    }
-
-    @Override
     public List<Service> getAllServices(long startTimestamp, long endTimestamp) throws IOException {
         StringBuilder sql = new StringBuilder();
         List<Object> condition = new ArrayList<>(5);
@@ -273,7 +228,7 @@ public class H2MetadataQueryDAO implements IMetadataQueryDAO {
                             String key = property.getKey();
                             String value = property.getValue().getAsString();
                             if (key.equals(InstanceTraffic.PropertyUtil.LANGUAGE)) {
-                                serviceInstance.setLanguage(LanguageTrans.INSTANCE.value(value));
+                                serviceInstance.setLanguage(Language.value(value));
                             } else {
                                 serviceInstance.getAttributes().add(new Attribute(key, value));
                             }
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/H2MetricsQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2MetricsQueryDAO.java
index 4ab5ca3..db5cbfd 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2MetricsQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2MetricsQueryDAO.java
@@ -26,17 +26,17 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import org.apache.skywalking.oap.server.core.analysis.DownSampling;
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValue;
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValueHashMap;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
-import org.apache.skywalking.oap.server.core.analysis.metrics.ThermodynamicMetrics;
-import org.apache.skywalking.oap.server.core.query.entity.IntValues;
-import org.apache.skywalking.oap.server.core.query.entity.KVInt;
-import org.apache.skywalking.oap.server.core.query.entity.Thermodynamic;
+import org.apache.skywalking.oap.server.core.query.PointOfTime;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.MetricsCondition;
 import org.apache.skywalking.oap.server.core.query.sql.Function;
-import org.apache.skywalking.oap.server.core.query.sql.KeyValues;
-import org.apache.skywalking.oap.server.core.query.sql.Where;
+import org.apache.skywalking.oap.server.core.query.type.HeatMap;
+import org.apache.skywalking.oap.server.core.query.type.IntValues;
+import org.apache.skywalking.oap.server.core.query.type.KVInt;
+import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
+import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
 
@@ -49,9 +49,10 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
     }
 
     @Override
-    public IntValues getValues(String tableName, DownSampling downsampling, long startTB, long endTB, Where where,
-                               String valueCName, Function function) throws IOException {
-        List<KeyValues> whereKeyValues = where.getKeyValues();
+    public int readMetricsValue(final MetricsCondition condition,
+                                String valueColumnName,
+                                final Duration duration) throws IOException {
+        final Function function = ValueColumnMetadata.INSTANCE.getValueFunction(condition.getName());
         String op;
         switch (function) {
             case Avg:
@@ -60,56 +61,46 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
             default:
                 op = "sum";
         }
-        List<String> ids = new ArrayList<>(20);
-        StringBuilder whereSql = new StringBuilder();
-        if (whereKeyValues.size() > 0) {
-            whereSql.append("(");
-            for (int i = 0; i < whereKeyValues.size(); i++) {
-                if (i != 0) {
-                    whereSql.append(" or ");
-                }
-                KeyValues keyValues = whereKeyValues.get(i);
-
-                StringBuilder valueCollection = new StringBuilder();
-                List<String> values = keyValues.getValues();
-                for (int valueIdx = 0; valueIdx < values.size(); valueIdx++) {
-                    if (valueIdx != 0) {
-                        valueCollection.append(",");
-                    }
-                    String id = values.get(valueIdx);
-                    ids.add(id);
-                    valueCollection.append("'").append(id).append("'");
-                }
-                whereSql.append(keyValues.getKey()).append(" in (").append(valueCollection).append(")");
-            }
-            whereSql.append(") and ");
+        StringBuilder sql = new StringBuilder(
+            "select " + Metrics.ENTITY_ID + " id, " + op + "(" + valueColumnName + ") value from " + condition.getName() + " where ");
+        final String entityId = condition.getEntity().buildId();
+        List<Object> parameters = new ArrayList();
+        if (entityId != null) {
+            sql.append(Metrics.ENTITY_ID + " = ? and ");
+            parameters.add(entityId);
         }
+        sql.append(Metrics.TIME_BUCKET + ">= ? and " + Metrics.TIME_BUCKET + "<=?" + " group by " + Metrics.ENTITY_ID);
+        parameters.add(duration.getStartTimeBucket());
+        parameters.add(duration.getEndTimeBucket());
 
-        IntValues intValues = new IntValues();
         try (Connection connection = h2Client.getConnection()) {
             try (ResultSet resultSet = h2Client.executeQuery(
                 connection,
-                "select " + Metrics.ENTITY_ID + " id, " + op + "(" + valueCName + ") value from " + tableName + " where " + whereSql + Metrics.TIME_BUCKET + ">= ? and " + Metrics.TIME_BUCKET + "<=?" + " group by " + Metrics.ENTITY_ID,
-                startTB, endTB
+                sql.toString(),
+                parameters.toArray(new Object[0])
             )) {
-
                 while (resultSet.next()) {
-                    KVInt kv = new KVInt();
-                    kv.setId(resultSet.getString("id"));
-                    kv.setValue(resultSet.getLong("value"));
-                    intValues.addKVInt(kv);
+                    return resultSet.getInt("value");
                 }
             }
         } catch (SQLException e) {
             throw new IOException(e);
         }
-        return intValues;
+        return ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName());
     }
 
     @Override
-    public IntValues getLinearIntValues(String tableName, DownSampling downsampling, List<String> ids,
-                                        String valueCName) throws IOException {
-        StringBuilder sql = new StringBuilder("select id, " + valueCName + " from " + tableName + " where id in (");
+    public MetricsValues readMetricsValues(final MetricsCondition condition,
+                                           final String valueColumnName,
+                                           final Duration duration) throws IOException {
+        final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
+        List<String> ids = new ArrayList<>(pointOfTimes.size());
+        pointOfTimes.forEach(pointOfTime -> {
+            ids.add(pointOfTime.id(condition.getEntity().buildId()));
+        });
+
+        StringBuilder sql = new StringBuilder(
+            "select id, " + valueColumnName + " from " + condition.getName() + " where id in (");
         List<Object> parameters = new ArrayList();
         for (int i = 0; i < ids.size(); i++) {
             if (i == 0) {
@@ -121,7 +112,9 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
         }
         sql.append(")");
 
-        IntValues intValues = new IntValues();
+        MetricsValues metricsValues = new MetricsValues();
+        // Label is null, because in readMetricsValues, no label parameter.
+        final IntValues intValues = metricsValues.getValues();
 
         try (Connection connection = h2Client.getConnection()) {
 
@@ -130,7 +123,7 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
                 while (resultSet.next()) {
                     KVInt kv = new KVInt();
                     kv.setId(resultSet.getString("id"));
-                    kv.setValue(resultSet.getLong(valueCName));
+                    kv.setValue(resultSet.getLong(valueColumnName));
                     intValues.addKVInt(kv);
                 }
             }
@@ -138,16 +131,26 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
             throw new IOException(e);
         }
 
-        return orderWithDefault0(intValues, ids);
+        metricsValues.setValues(
+            Util.sortValues(intValues, ids, ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName()))
+        );
+        return metricsValues;
     }
 
     @Override
-    public IntValues[] getMultipleLinearIntValues(String tableName,
-                                                  DownSampling downsampling,
-                                                  List<String> ids,
-                                                  final List<Integer> linearIndex,
-                                                  String valueCName) throws IOException {
-        StringBuilder sql = new StringBuilder("select id, " + valueCName + " from " + tableName + " where id in (");
+    public List<MetricsValues> readLabeledMetricsValues(final MetricsCondition condition,
+                                                        final String valueColumnName,
+                                                        final List<String> labels,
+                                                        final Duration duration) throws IOException {
+        final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
+        List<String> ids = new ArrayList<>(pointOfTimes.size());
+        pointOfTimes.forEach(pointOfTime -> {
+            ids.add(pointOfTime.id(condition.getEntity().buildId()));
+        });
+
+        StringBuilder sql = new StringBuilder(
+            "select id, " + valueColumnName + " from " + condition.getName() + " where id in (");
+
         List<Object> parameters = new ArrayList();
         for (int i = 0; i < ids.size(); i++) {
             if (i == 0) {
@@ -159,10 +162,13 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
         }
         sql.append(")");
 
-        IntValues[] intValuesArray = new IntValues[linearIndex.size()];
-        for (int i = 0; i < intValuesArray.length; i++) {
-            intValuesArray[i] = new IntValues();
-        }
+        Map<String, MetricsValues> labeledValues = new HashMap<>(labels.size());
+        labels.forEach(label -> {
+            MetricsValues labelValue = new MetricsValues();
+            labelValue.setLabel(label);
+
+            labeledValues.put(label, labelValue);
+        });
 
         try (Connection connection = h2Client.getConnection()) {
             try (ResultSet resultSet = h2Client.executeQuery(
@@ -170,56 +176,42 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
                 while (resultSet.next()) {
                     String id = resultSet.getString("id");
 
-                    IntKeyLongValueHashMap multipleValues = new IntKeyLongValueHashMap(5);
-                    multipleValues.toObject(resultSet.getString(valueCName));
+                    DataTable multipleValues = new DataTable(5);
+                    multipleValues.toObject(resultSet.getString(valueColumnName));
 
-                    for (int i = 0; i < linearIndex.size(); i++) {
-                        Integer index = linearIndex.get(i);
+                    labels.forEach(label -> {
+                        final Long data = multipleValues.get(label);
+                        final IntValues values = labeledValues.get(label).getValues();
                         KVInt kv = new KVInt();
                         kv.setId(id);
-                        kv.setValue(multipleValues.get(index).getValue());
-                        intValuesArray[i].addKVInt(kv);
-                    }
+                        kv.setValue(data);
+                        values.addKVInt(kv);
+                    });
                 }
             }
         } catch (SQLException e) {
             throw new IOException(e);
         }
 
-        return orderWithDefault0(intValuesArray, ids);
+        return Util.sortValues(
+            new ArrayList<>(labeledValues.values()),
+            ids,
+            ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName())
+        );
     }
 
-    /**
-     * Make sure the order is same as the expected order, and keep default value as 0.
-     */
-    private IntValues orderWithDefault0(IntValues origin, List<String> expectedOrder) {
-        IntValues intValues = new IntValues();
-
-        expectedOrder.forEach(id -> {
-            KVInt e = new KVInt();
-            e.setId(id);
-            e.setValue(origin.findValue(id, 0));
-            intValues.addKVInt(e);
+    @Override
+    public HeatMap readHeatMap(final MetricsCondition condition,
+                               final String valueColumnName,
+                               final Duration duration) throws IOException {
+        final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
+        List<String> ids = new ArrayList<>(pointOfTimes.size());
+        pointOfTimes.forEach(pointOfTime -> {
+            ids.add(pointOfTime.id(condition.getEntity().buildId()));
         });
 
-        return intValues;
-    }
-
-    /**
-     * Make sure the order is same as the expected order, and keep default value as 0.
-     */
-    private IntValues[] orderWithDefault0(IntValues[] origin, List<String> expectedOrder) {
-        for (int i = 0; i < origin.length; i++) {
-            origin[i] = orderWithDefault0(origin[i], expectedOrder);
-        }
-        return origin;
-    }
-
-    @Override
-    public Thermodynamic getThermodynamic(String tableName, DownSampling downsampling, List<String> ids,
-                                          String valueCName) throws IOException {
         StringBuilder sql = new StringBuilder(
-            "select " + ThermodynamicMetrics.STEP + " step, " + ThermodynamicMetrics.NUM_OF_STEPS + " num_of_steps, " + ThermodynamicMetrics.DETAIL_GROUP + " detail_group, " + "id " + " from " + tableName + " where id in (");
+            "select id, " + valueColumnName + " dataset, id from " + condition.getName() + " where id in (");
         List<Object> parameters = new ArrayList();
         for (int i = 0; i < ids.size(); i++) {
             if (i == 0) {
@@ -231,50 +223,19 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
         }
         sql.append(")");
 
-        List<List<Long>> thermodynamicValueCollection = new ArrayList<>();
-        Map<String, List<Long>> thermodynamicValueMatrix = new HashMap<>();
-
         try (Connection connection = h2Client.getConnection()) {
-            Thermodynamic thermodynamic = new Thermodynamic();
-            int numOfSteps = 0;
-            int axisYStep = 0;
+            HeatMap heatMap = new HeatMap();
             try (ResultSet resultSet = h2Client.executeQuery(
                 connection, sql.toString(), parameters.toArray(new Object[0]))) {
 
                 while (resultSet.next()) {
-                    axisYStep = resultSet.getInt("step");
-                    String id = resultSet.getString("id");
-                    numOfSteps = resultSet.getInt("num_of_steps") + 1;
-                    String value = resultSet.getString("detail_group");
-                    IntKeyLongValueHashMap intKeyLongValues = new IntKeyLongValueHashMap(5);
-                    intKeyLongValues.toObject(value);
-
-                    List<Long> axisYValues = new ArrayList<>();
-                    for (int i = 0; i < numOfSteps; i++) {
-                        axisYValues.add(0L);
-                    }
-
-                    for (IntKeyLongValue intKeyLongValue : intKeyLongValues.values()) {
-                        axisYValues.set(intKeyLongValue.getKey(), intKeyLongValue.getValue());
-                    }
-
-                    thermodynamicValueMatrix.put(id, axisYValues);
+                    heatMap.buildColumn(resultSet.getString("id"), resultSet.getString("dataset"));
                 }
-
-                // try to add default values when there is no data in that time bucket.
-                ids.forEach(id -> {
-                    if (thermodynamicValueMatrix.containsKey(id)) {
-                        thermodynamicValueCollection.add(thermodynamicValueMatrix.get(id));
-                    } else {
-                        thermodynamicValueCollection.add(new ArrayList<>());
-                    }
-                });
             }
 
-            thermodynamic.fromMatrixData(thermodynamicValueCollection, numOfSteps);
-            thermodynamic.setAxisYStep(axisYStep);
+            heatMap.fixMissingColumns(ids);
 
-            return thermodynamic;
+            return heatMap;
         } catch (SQLException e) {
             throw new IOException(e);
         }
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/H2ProfileTaskLogQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileTaskLogQueryDAO.java
index 896548a..d07292a 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileTaskLogQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileTaskLogQueryDAO.java
@@ -19,8 +19,8 @@
 package org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao;
 
 import org.apache.skywalking.oap.server.core.profile.ProfileTaskLogRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLog;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLogOperationType;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLog;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLogOperationType;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.JDBCClientException;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
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/H2ProfileTaskQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileTaskQueryDAO.java
index 8d31ee2..2ff0095 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileTaskQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileTaskQueryDAO.java
@@ -27,7 +27,7 @@ import java.util.LinkedList;
 import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.profile.ProfileTaskRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
+import org.apache.skywalking.oap.server.core.query.type.ProfileTask;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.JDBCClientException;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
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/H2ProfileThreadSnapshotQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileThreadSnapshotQueryDAO.java
index b0a9970..9791673 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileThreadSnapshotQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileThreadSnapshotQueryDAO.java
@@ -31,7 +31,7 @@ import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
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/H2TableInstaller.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TableInstaller.java
index 42c68ba..4d10bf4 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TableInstaller.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TableInstaller.java
@@ -23,7 +23,7 @@ import java.sql.Connection;
 import java.sql.SQLException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.oap.server.core.analysis.NodeType;
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValueHashMap;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 import org.apache.skywalking.oap.server.core.storage.StorageException;
 import org.apache.skywalking.oap.server.core.storage.model.ColumnName;
 import org.apache.skywalking.oap.server.core.storage.model.Model;
@@ -98,7 +98,7 @@ public class H2TableInstaller extends ModelInstaller {
             return "DOUBLE";
         } else if (String.class.equals(type)) {
             return "VARCHAR(" + column.getLength() + ")";
-        } else if (IntKeyLongValueHashMap.class.equals(type)) {
+        } else if (DataTable.class.equals(type)) {
             return "VARCHAR(20000)";
         } else if (byte[].class.equals(type)) {
             return "MEDIUMTEXT";
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/H2TopNRecordsQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TopNRecordsQueryDAO.java
index 2de5ead..2f9a22d 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TopNRecordsQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TopNRecordsQueryDAO.java
@@ -24,9 +24,13 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
+import org.apache.skywalking.apm.util.StringUtil;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.analysis.topn.TopN;
-import org.apache.skywalking.oap.server.core.query.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.TopNRecord;
+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.SelectedRecord;
 import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
 
@@ -38,35 +42,39 @@ public class H2TopNRecordsQueryDAO implements ITopNRecordsQueryDAO {
     }
 
     @Override
-    public List<TopNRecord> getTopNRecords(long startSecondTB, long endSecondTB, String metricName, String serviceId,
-        int topN, Order order) throws IOException {
-        StringBuilder sql = new StringBuilder("select * from " + metricName + " where ");
+    public List<SelectedRecord> readSampledRecords(final TopNCondition condition,
+                                                   final Duration duration) throws IOException {
+        StringBuilder sql = new StringBuilder("select * from " + condition.getName() + " where ");
         List<Object> parameters = new ArrayList<>(10);
 
-        sql.append(" service_id = ? ");
-        parameters.add(serviceId);
+        if (StringUtil.isNotEmpty(condition.getParentService())) {
+            sql.append(" service_id = ? ");
+            final String serviceId = IDManager.ServiceID.buildId(condition.getParentService(), condition.isNormal());
+            parameters.add(serviceId);
+        }
 
         sql.append(" and ").append(TopN.TIME_BUCKET).append(" >= ?");
-        parameters.add(startSecondTB);
+        parameters.add(duration.getStartTimeBucket());
         sql.append(" and ").append(TopN.TIME_BUCKET).append(" <= ?");
-        parameters.add(endSecondTB);
+        parameters.add(duration.getEndTimeBucket());
 
         sql.append(" order by ").append(TopN.LATENCY);
-        if (order.equals(Order.DES)) {
+        if (condition.getOrder().equals(Order.DES)) {
             sql.append(" desc ");
         } else {
             sql.append(" asc ");
         }
-        sql.append(" limit ").append(topN);
+        sql.append(" limit ").append(condition.getTopN());
 
-        List<TopNRecord> results = new ArrayList<>();
+        List<SelectedRecord> results = new ArrayList<>();
         try (Connection connection = h2Client.getConnection()) {
-            try (ResultSet resultSet = h2Client.executeQuery(connection, sql.toString(), parameters.toArray(new Object[0]))) {
+            try (ResultSet resultSet = h2Client.executeQuery(
+                connection, sql.toString(), parameters.toArray(new Object[0]))) {
                 while (resultSet.next()) {
-                    TopNRecord record = new TopNRecord();
-                    record.setStatement(resultSet.getString(TopN.STATEMENT));
-                    record.setTraceId(resultSet.getString(TopN.TRACE_ID));
-                    record.setLatency(resultSet.getLong(TopN.LATENCY));
+                    SelectedRecord record = new SelectedRecord();
+                    record.setName(resultSet.getString(TopN.STATEMENT));
+                    record.setRefId(resultSet.getString(TopN.TRACE_ID));
+                    record.setValue(resultSet.getString(TopN.LATENCY));
                     results.add(record);
                 }
             }
@@ -76,4 +84,5 @@ public class H2TopNRecordsQueryDAO implements ITopNRecordsQueryDAO {
 
         return results;
     }
+
 }
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/H2TopologyQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TopologyQueryDAO.java
index 6000aa9..8a5e9eb 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TopologyQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TopologyQueryDAO.java
@@ -24,14 +24,13 @@ 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.manual.relation.endpoint.EndpointRelationServerSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.instance.ServiceInstanceRelationClientSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.instance.ServiceInstanceRelationServerSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.service.ServiceRelationClientSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.manual.relation.service.ServiceRelationServerSideMetrics;
 import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
-import org.apache.skywalking.oap.server.core.query.entity.Call;
+import org.apache.skywalking.oap.server.core.query.type.Call;
 import org.apache.skywalking.oap.server.core.source.DetectPoint;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
@@ -44,8 +43,7 @@ public class H2TopologyQueryDAO implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(DownSampling downsampling,
-                                                                          long startTB,
+    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(long startTB,
                                                                           long endTB,
                                                                           List<String> serviceIds) throws IOException {
         return loadServiceCalls(
@@ -56,8 +54,7 @@ public class H2TopologyQueryDAO implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(DownSampling downsampling,
-                                                                         long startTB,
+    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(long startTB,
                                                                          long endTB,
                                                                          List<String> serviceIds) throws IOException {
         return loadServiceCalls(
@@ -68,7 +65,7 @@ public class H2TopologyQueryDAO implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(DownSampling downsampling, long startTB,
+    public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(long startTB,
                                                                           long endTB) throws IOException {
         return loadServiceCalls(
             ServiceRelationServerSideMetrics.INDEX_NAME, startTB, endTB,
@@ -78,7 +75,7 @@ public class H2TopologyQueryDAO implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(DownSampling downsampling, long startTB,
+    public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(long startTB,
                                                                          long endTB) throws IOException {
         return loadServiceCalls(
             ServiceRelationClientSideMetrics.INDEX_NAME, startTB, endTB,
@@ -90,7 +87,6 @@ public class H2TopologyQueryDAO implements ITopologyQueryDAO {
     @Override
     public List<Call.CallDetail> loadInstanceRelationDetectedAtServerSide(String clientServiceId,
                                                                           String serverServiceId,
-                                                                          DownSampling downsampling,
                                                                           long startTB,
                                                                           long endTB) throws IOException {
         return loadServiceInstanceCalls(
@@ -104,7 +100,6 @@ public class H2TopologyQueryDAO implements ITopologyQueryDAO {
     @Override
     public List<Call.CallDetail> loadInstanceRelationDetectedAtClientSide(String clientServiceId,
                                                                           String serverServiceId,
-                                                                          DownSampling downsampling,
                                                                           long startTB,
                                                                           long endTB) throws IOException {
         return loadServiceInstanceCalls(
@@ -116,8 +111,7 @@ public class H2TopologyQueryDAO implements ITopologyQueryDAO {
     }
 
     @Override
-    public List<Call.CallDetail> loadEndpointRelation(DownSampling downsampling,
-                                                      long startTB,
+    public List<Call.CallDetail> loadEndpointRelation(long startTB,
                                                       long endTB,
                                                       String destEndpointId) throws IOException {
         List<Call.CallDetail> calls = loadEndpointFromSide(
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/H2TraceQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TraceQueryDAO.java
index 54cfb65..1928ef3 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TraceQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TraceQueryDAO.java
@@ -29,11 +29,11 @@ import java.util.Collections;
 import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.Span;
-import org.apache.skywalking.oap.server.core.query.entity.TraceBrief;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.Span;
+import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
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 6a32f9b..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.entity.Order;
-import org.apache.skywalking.oap.server.core.query.entity.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;
-    }
 }
diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLAlarmQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLAlarmQueryDAO.java
index 1f7f172..aea77c8 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLAlarmQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLAlarmQueryDAO.java
@@ -19,9 +19,9 @@
 package org.apache.skywalking.oap.server.storage.plugin.jdbc.mysql;
 
 import org.apache.skywalking.oap.server.core.alarm.AlarmRecord;
-import org.apache.skywalking.oap.server.core.query.entity.AlarmMessage;
-import org.apache.skywalking.oap.server.core.query.entity.Alarms;
-import org.apache.skywalking.oap.server.core.query.entity.Scope;
+import org.apache.skywalking.oap.server.core.query.type.AlarmMessage;
+import org.apache.skywalking.oap.server.core.query.type.Alarms;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
 import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
 import org.elasticsearch.common.Strings;
diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLTableInstaller.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLTableInstaller.java
index 47fbb78..839fefb 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLTableInstaller.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLTableInstaller.java
@@ -22,7 +22,7 @@ import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValueHashMap;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 import org.apache.skywalking.oap.server.core.storage.StorageException;
 import org.apache.skywalking.oap.server.core.storage.model.ExtraQueryIndex;
 import org.apache.skywalking.oap.server.core.storage.model.Model;
@@ -105,7 +105,7 @@ public class MySQLTableInstaller extends H2TableInstaller {
 
     @Override
     protected String getColumnType(final ModelColumn column) {
-        if (IntKeyLongValueHashMap.class.equals(column.getType())) {
+        if (DataTable.class.equals(column.getType())) {
             return "MEDIUMTEXT";
         }
         return super.getColumnType(column);
diff --git a/oap-server/server-storage-plugin/storage-zipkin-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/zipkin/elasticsearch/ZipkinTraceQueryEsDAO.java b/oap-server/server-storage-plugin/storage-zipkin-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/zipkin/elasticsearch/ZipkinTraceQueryEsDAO.java
index 94f3f2b..45f090a 100644
--- a/oap-server/server-storage-plugin/storage-zipkin-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/zipkin/elasticsearch/ZipkinTraceQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-zipkin-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/zipkin/elasticsearch/ZipkinTraceQueryEsDAO.java
@@ -27,14 +27,14 @@ import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
-import org.apache.skywalking.oap.server.core.query.entity.KeyValue;
-import org.apache.skywalking.oap.server.core.query.entity.LogEntity;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.Ref;
-import org.apache.skywalking.oap.server.core.query.entity.RefType;
-import org.apache.skywalking.oap.server.core.query.entity.TraceBrief;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.KeyValue;
+import org.apache.skywalking.oap.server.core.query.type.LogEntity;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.Ref;
+import org.apache.skywalking.oap.server.core.query.type.RefType;
+import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
@@ -178,7 +178,7 @@ public class ZipkinTraceQueryEsDAO extends EsDAO implements ITraceQueryDAO {
     }
 
     @Override
-    public List<org.apache.skywalking.oap.server.core.query.entity.Span> doFlexibleTraceQuery(
+    public List<org.apache.skywalking.oap.server.core.query.type.Span> doFlexibleTraceQuery(
         String traceId) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
         sourceBuilder.query(QueryBuilders.termQuery(TRACE_ID, traceId));
@@ -187,14 +187,14 @@ public class ZipkinTraceQueryEsDAO extends EsDAO implements ITraceQueryDAO {
 
         SearchResponse response = getClient().search(ZipkinSpanRecord.INDEX_NAME, sourceBuilder);
 
-        List<org.apache.skywalking.oap.server.core.query.entity.Span> spanList = new ArrayList<>();
+        List<org.apache.skywalking.oap.server.core.query.type.Span> spanList = new ArrayList<>();
 
         for (SearchHit searchHit : response.getHits().getHits()) {
             String serviceId = (String) searchHit.getSourceAsMap().get(SERVICE_ID);
             String dataBinaryBase64 = (String) searchHit.getSourceAsMap().get(SegmentRecord.DATA_BINARY);
             Span span = SpanBytesDecoder.PROTO3.decodeOne(Base64.getDecoder().decode(dataBinaryBase64));
 
-            org.apache.skywalking.oap.server.core.query.entity.Span swSpan = new org.apache.skywalking.oap.server.core.query.entity.Span();
+            org.apache.skywalking.oap.server.core.query.type.Span swSpan = new org.apache.skywalking.oap.server.core.query.type.Span();
 
             swSpan.setTraceId(span.traceId());
             swSpan.setEndpointName(span.name());
diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/main/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileSnapshotDumper.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/main/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileSnapshotDumper.java
index 5a5e54b..37eb57c 100644
--- a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/main/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileSnapshotDumper.java
+++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/main/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileSnapshotDumper.java
@@ -22,7 +22,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.apm.network.language.profile.v3.ThreadSnapshot;
 import org.apache.skywalking.apm.network.language.profile.v3.ThreadStack;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzeTimeRange;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/main/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfiledBasicInfo.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/main/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfiledBasicInfo.java
index ff00823..0545edc 100644
--- a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/main/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfiledBasicInfo.java
+++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/main/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfiledBasicInfo.java
@@ -24,9 +24,9 @@ import org.apache.commons.io.FileUtils;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.query.ProfileTaskQueryService;
 import org.apache.skywalking.oap.server.core.query.TraceQueryService;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
-import org.apache.skywalking.oap.server.core.query.entity.Span;
-import org.apache.skywalking.oap.server.core.query.entity.Trace;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.Span;
+import org.apache.skywalking.oap.server.core.query.type.Trace;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileAnalyzeSnapshotDAO.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileAnalyzeSnapshotDAO.java
index 80175b4..98ae10b 100644
--- a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileAnalyzeSnapshotDAO.java
+++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileAnalyzeSnapshotDAO.java
@@ -22,7 +22,7 @@ import com.google.common.primitives.Ints;
 import org.apache.skywalking.apm.network.language.profile.v3.ThreadSnapshot;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 
 import java.io.IOException;
diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileExportedAnalyze.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileExportedAnalyze.java
index 8bc37c9..11d20e5 100644
--- a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileExportedAnalyze.java
+++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/ProfileExportedAnalyze.java
@@ -22,11 +22,11 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.apm.network.language.profile.v3.ThreadSnapshot;
 import org.apache.skywalking.oap.server.core.CoreModuleConfig;
 import org.apache.skywalking.oap.server.core.profile.analyze.ProfileAnalyzer;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzation;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileStackElement;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileStackTree;
-import org.apache.skywalking.oap.server.core.query.entity.Span;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzation;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzeTimeRange;
+import org.apache.skywalking.oap.server.core.query.type.ProfileStackElement;
+import org.apache.skywalking.oap.server.core.query.type.ProfileStackTree;
+import org.apache.skywalking.oap.server.core.query.type.Span;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.library.util.CollectionUtils;
 
diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileExportSnapshotDAO.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileExportSnapshotDAO.java
index 10e5524..d275acc 100644
--- a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileExportSnapshotDAO.java
+++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileExportSnapshotDAO.java
@@ -21,7 +21,7 @@ package org.apache.skywalking.oap.server.tool.profile.exporter.test;
 import org.apache.skywalking.apm.network.language.profile.v3.ThreadStack;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
 import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
-import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
+import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 
 import java.io.IOException;
diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileSnapshotExporterTest.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileSnapshotExporterTest.java
index 0fc8e2e..189c2aa 100644
--- a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileSnapshotExporterTest.java
+++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileSnapshotExporterTest.java
@@ -31,7 +31,7 @@ import org.apache.skywalking.oap.server.core.config.ComponentLibraryCatalogServi
 import org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogService;
 import org.apache.skywalking.oap.server.core.query.ProfileTaskQueryService;
 import org.apache.skywalking.oap.server.core.query.TraceQueryService;
-import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange;
+import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzeTimeRange;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTraceDAO.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTraceDAO.java
index a7bdd7b..fe499d3 100644
--- a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTraceDAO.java
+++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTraceDAO.java
@@ -24,10 +24,10 @@ import java.util.List;
 import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject;
 import org.apache.skywalking.apm.network.language.agent.v3.SpanObject;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
-import org.apache.skywalking.oap.server.core.query.entity.QueryOrder;
-import org.apache.skywalking.oap.server.core.query.entity.Span;
-import org.apache.skywalking.oap.server.core.query.entity.TraceBrief;
-import org.apache.skywalking.oap.server.core.query.entity.TraceState;
+import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import org.apache.skywalking.oap.server.core.query.type.Span;
+import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
+import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 
 public class ProfileTraceDAO implements ITraceQueryDAO {
diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-server-mock/src/main/java/org/apache/skywalking/oap/server/tool/profile/core/MockCoreModuleProvider.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-server-mock/src/main/java/org/apache/skywalking/oap/server/tool/profile/core/MockCoreModuleProvider.java
index 04413b9..b48790f 100755
--- a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-server-mock/src/main/java/org/apache/skywalking/oap/server/tool/profile/core/MockCoreModuleProvider.java
+++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-server-mock/src/main/java/org/apache/skywalking/oap/server/tool/profile/core/MockCoreModuleProvider.java
@@ -36,7 +36,7 @@ import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
 import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
 import org.apache.skywalking.oap.server.core.query.LogQueryService;
 import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
-import org.apache.skywalking.oap.server.core.query.MetricQueryService;
+import org.apache.skywalking.oap.server.core.query.MetricsQueryService;
 import org.apache.skywalking.oap.server.core.query.ProfileTaskQueryService;
 import org.apache.skywalking.oap.server.core.query.TopNRecordsQueryService;
 import org.apache.skywalking.oap.server.core.query.TopologyQueryService;
@@ -132,7 +132,7 @@ public class MockCoreModuleProvider extends CoreModuleProvider {
             NetworkAddressAliasCache.class, new NetworkAddressAliasCache(moduleConfig));
 
         this.registerServiceImplementation(TopologyQueryService.class, new TopologyQueryService(getManager()));
-        this.registerServiceImplementation(MetricQueryService.class, new MetricQueryService(getManager()));
+        this.registerServiceImplementation(MetricsQueryService.class, new MetricsQueryService(getManager()));
         this.registerServiceImplementation(TraceQueryService.class, new TraceQueryService(getManager()));
         this.registerServiceImplementation(LogQueryService.class, new LogQueryService(getManager()));
         this.registerServiceImplementation(MetadataQueryService.class, new MetadataQueryService(getManager()));
diff --git a/skywalking-ui b/skywalking-ui
index 905b896..52a56d3 160000
--- a/skywalking-ui
+++ b/skywalking-ui
@@ -1 +1 @@
-Subproject commit 905b89687a74a306e89f3fbafe43dd3d7ff80eaf
+Subproject commit 52a56d3ee273a3629d3ac48ba7eb99d8ba694ca9