Repository: alibaba/GraphScope (language: python)

Issue:
Introduce Statistics Abstraction in Metadata in GIE
**Is your feature request related to a problem? Please describe.**

Currently, the CBO in GOpt relies on high-order statistics provided by GLogue for cost estimation, where GLogue further depends on low-order statistics information, namely the count of each vertex and edge type, to form its estimations. As of now, we simply retrieves (low-order) statistics information by reading from a file.

To enhance the modularity and scalability of our system, there's a need to refactor the way statistics are managed. This includes:

- [x] Introduce Statistics Abstraction in Metadata
- [x] In GOpt, build GLogue from Metadata

In Storages, Each storage should be responsible for providing its own statistics information, including:
- [x]  ExpStore
- [x] Groot
- [ ] Vineyard
- [x] Mcsr
etc.


Discussion / hints:

Fix patch:
diff --git a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/api/GraphSchema.java b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/api/GraphSchema.java
index af88053446a4..d7b93df9ce77 100644
--- a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/api/GraphSchema.java
+++ b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/api/GraphSchema.java
@@ -43,5 +43,5 @@ public interface GraphSchema {
      *
      * @return The schema version
      */
-    int getVersion();
+    String getVersion();
 }
diff --git a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/api/GraphStatistics.java b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/api/GraphStatistics.java
new file mode 100644
index 000000000000..3a88a77d643c
--- /dev/null
+++ b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/api/GraphStatistics.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.groot.common.schema.api;
+
+import java.util.Optional;
+
+public interface GraphStatistics {
+
+    /**
+     * Gets the Cardinality of all nodes regardless of types.
+     */
+    Long getVertexCount();
+
+    /**
+     * Gets the Cardinality of all relationships regardless of types.
+     */
+    Long getEdgeCount();
+
+    /**
+     * Get the cardinality for the given vertex typeId
+     *
+     * @param vertexTypeId the vertex type id
+     * @return the cardinality of the given vertex type id
+     */
+    Long getVertexTypeCount(Integer vertexTypeId);
+
+    /*
+     * Get the cardinality of all relationships (a)-[r]->(b), where
+     *
+     *   a has the type `sourceTypeId`, or any types if `sourceTypeId` is None
+     *   b has the type `targetTypeId`, or any types if `targetTypeId` is None
+     *   r has the type `edgeTypeId`, or any type if `edgeTypeId` is None
+     *
+     * @param sourceTypeId the source vertex type id, edgeTypeId the edge type id, targetTypeId the target vertex type id
+     * @return the cardinality of the given relationship
+     */
+    Long getEdgeTypeCount(
+            Optional<Integer> sourceTypeId,
+            Optional<Integer> edgeTypeId,
+            Optional<Integer> targetTypeId);
+
+    /**
+     * Get the version of the statistics, which should be consist with the version of schema
+     *
+     * @return The version of the statistics
+     */
+    String getVersion();
+}
diff --git a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/impl/DefaultGraphSchema.java b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/impl/DefaultGraphSchema.java
index 8e1e9483cfd1..0ae122a383cd 100644
--- a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/impl/DefaultGraphSchema.java
+++ b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/impl/DefaultGraphSchema.java
@@ -136,8 +136,8 @@ public Map<GraphElement, GraphProperty> getPropertyList(int propId) {
     }
 
     @Override
-    public int getVersion() {
-        return 0;
+    public String getVersion() {
+        return "0";
     }
 
     public static GraphSchema buildSchemaFromJson(String schemaJson) {
diff --git a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/impl/DefaultGraphStatistics.java b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/impl/DefaultGraphStatistics.java
new file mode 100644
index 000000000000..1c029c0e3dfe
--- /dev/null
+++ b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/impl/DefaultGraphStatistics.java
@@ -0,0 +1,97 @@
+/**
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.groot.common.schema.impl;
+
+import com.alibaba.graphscope.groot.common.schema.api.GraphStatistics;
+import com.alibaba.graphscope.groot.common.schema.wrapper.EdgeKind;
+import com.alibaba.graphscope.groot.common.schema.wrapper.LabelId;
+import com.google.common.collect.Maps;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+public class DefaultGraphStatistics implements GraphStatistics {
+    private static final Logger logger = LoggerFactory.getLogger(DefaultGraphStatistics.class);
+    private Map<LabelId, Long> vertexTypeCounts = Maps.newHashMap();
+    private Map<EdgeKind, Long> edgeTypeCounts = Maps.newHashMap();
+    private Long totalVertexCount;
+    private Long totalEdgeCount;
+
+    public DefaultGraphStatistics(
+            Map<LabelId, Long> vertexTypeCounts,
+            Map<EdgeKind, Long> edgeTypeCounts,
+            Long totalVertexCount,
+            Long totalEdgeCount) {
+        this.vertexTypeCounts = vertexTypeCounts;
+        this.edgeTypeCounts = edgeTypeCounts;
+        this.totalVertexCount = totalVertexCount;
+        this.totalEdgeCount = totalEdgeCount;
+    }
+
+    @Override
+    public String getVersion() {
+        return "0";
+    }
+
+    @Override
+    public Long getVertexCount() {
+        return totalVertexCount;
+    }
+
+    @Override
+    public Long getEdgeCount() {
+        return totalEdgeCount;
+    }
+
+    @Override
+    public Long getVertexTypeCount(Integer vertexTypeId) {
+        return vertexTypeCounts.get(new LabelId(vertexTypeId));
+    }
+
+    @Override
+    public Long getEdgeTypeCount(
+            Optional<Integer> sourceTypeId,
+            Optional<Integer> edgeTypeId,
+            Optional<Integer> targetTypeId) {
+        Long count =
+                edgeTypeCounts.entrySet().stream()
+                        .filter(
+                                entry ->
+                                        (!sourceTypeId.isPresent()
+                                                || entry.getKey()
+                                                        .getSrcVertexLabelId()
+                                                        .equals(new LabelId(sourceTypeId.get()))))
+                        .filter(
+                                entry ->
+                                        (!edgeTypeId.isPresent()
+                                                || entry.getKey()
+                                                        .getEdgeLabelId()
+                                                        .equals(new LabelId(edgeTypeId.get()))))
+                        .filter(
+                                entry ->
+                                        (!targetTypeId.isPresent()
+                                                || entry.getKey()
+                                                        .getDstVertexLabelId()
+                                                        .equals(new LabelId(targetTypeId.get()))))
+                        .collect(Collectors.summingLong(Map.Entry::getValue));
+
+        return count == null ? 0L : count;
+    }
+}
diff --git a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/mapper/GraphSchemaMapper.java b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/mapper/GraphSchemaMapper.java
index e4f2fa28d485..1884e0832c77 100644
--- a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/mapper/GraphSchemaMapper.java
+++ b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/mapper/GraphSchemaMapper.java
@@ -35,13 +35,13 @@
  */
 public class GraphSchemaMapper {
     private List<SchemaElementMapper> types;
-    private int version;
+    private String version;
 
     public List<SchemaElementMapper> getTypes() {
         return types;
     }
 
-    public int getVersion() {
+    public String getVersion() {
         return version;
     }
 
@@ -93,9 +93,9 @@ public static GraphSchemaMapper parseFromJson(String schemaJson) {
             GraphSchemaMapper graphSchema = new GraphSchemaMapper();
             JsonNode jsonNode = mapper.readTree(schemaJson);
             if (jsonNode.has("version")) {
-                graphSchema.version = jsonNode.get("version").asInt();
+                graphSchema.version = jsonNode.get("version").asText();
             } else {
-                graphSchema.version = 0;
+                graphSchema.version = "0";
             }
             graphSchema.types = new ArrayList<>();
             JsonNode typeArray = jsonNode.get("types");
diff --git a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/unified/Graph.java b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/unified/Graph.java
index 015cc2accdb6..4578f637da05 100644
--- a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/unified/Graph.java
+++ b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/unified/Graph.java
@@ -160,10 +160,10 @@ public Map<GraphElement, GraphProperty> getPropertyList(int propId) {
 
     @Override
     @JsonIgnore
-    public int getVersion() {
+    public String getVersion() {
         if (version == null) {
-            return 0;
+            return "0";
         }
-        return Integer.parseInt(version);
+        return version;
     }
 }
diff --git a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/wrapper/GraphDef.java b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/wrapper/GraphDef.java
index 5b391467c685..490d0759322e 100644
--- a/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/wrapper/GraphDef.java
+++ b/interactive_engine/common/src/main/java/com/alibaba/graphscope/groot/common/schema/wrapper/GraphDef.java
@@ -315,8 +315,8 @@ public Map<GraphElement, GraphProperty> getPropertyList(int propId) {
     }
 
     @Override
-    public int getVersion() {
-        return (int) version;
+    public String getVersion() {
+        return String.valueOf(version);
     }
 
     public long getSchemaVersion() {
diff --git a/interactive_engine/compiler/Makefile b/interactive_engine/compiler/Makefile
index f375e76291bb..83bd68241617 100644
--- a/interactive_engine/compiler/Makefile
+++ b/interactive_engine/compiler/Makefile
@@ -62,7 +62,7 @@ run:
 	  -Dphysical.opt.config=${physical.opt.config} \
 	  -Dgraph.planner.rules=${graph.planner.rules} \
 	  -Dgraph.planner.opt=${graph.planner.opt} \
-	  -Dgraph.planner.cbo.glogue.schema=${graph.planner.cbo.glogue.schema} \
+	  -Dgraph.statistics=${graph.statistics} \
 	  com.alibaba.graphscope.GraphServer ${config.path}
 
 # make physical_plan config.path='<path to the config file>'
diff --git a/interactive_engine/compiler/conf/ir.compiler.properties b/interactive_engine/compiler/conf/ir.compiler.properties
index 7f18a0271721..813297331f5e 100644
--- a/interactive_engine/compiler/conf/ir.compiler.properties
+++ b/interactive_engine/compiler/conf/ir.compiler.properties
@@ -22,7 +22,7 @@ graph.planner.opt: RBO
 graph.planner.rules: FilterIntoJoinRule, FilterMatchRule, ExtendIntersectRule, ExpandGetVFusionRule
 
 # set file path of glogue input statistics
-# graph.planner.cbo.glogue.schema: src/test/resources/statistics/modern_statistics.txt
+# graph.statistics: src/test/resources/statistics/modern_statistics.json
 
 # set stored procedures directory path
 # graph.stored.procedures: <your stored procedures directory path>
diff --git a/interactive_engine/compiler/ir_experimental_ci.sh b/interactive_engine/compiler/ir_experimental_ci.sh
index e4a96b453c4a..28f385c44ee0 100755
--- a/interactive_engine/compiler/ir_experimental_ci.sh
+++ b/interactive_engine/compiler/ir_experimental_ci.sh
@@ -21,7 +21,7 @@ fi
 
 # Test2: run gremlin standard tests on experimental store via calcite-based ir
 # restart compiler service
-cd ${base_dir} && make run gremlin.script.language.name=antlr_gremlin_calcite physical.opt.config=proto graph.planner.opt=CBO graph.planner.cbo.glogue.schema=src/test/resources/statistics/modern_statistics.txt &
+cd ${base_dir} && make run gremlin.script.language.name=antlr_gremlin_calcite physical.opt.config=proto graph.planner.opt=CBO graph.statistics=./src/test/resources/statistics/modern_statistics.json &
 sleep 5s
 # run gremlin standard tests to test calcite-based IR layer
 cd ${base_dir} && make gremlin_calcite_test
@@ -42,7 +42,7 @@ RUST_LOG=info DATA_PATH=/tmp/gstest/modern_graph_exp_bin PARTITION_ID=0 ./start_
 cd ${base_dir}/../executor/ir/target/release &&
 RUST_LOG=info DATA_PATH=/tmp/gstest/modern_graph_exp_bin PARTITION_ID=1 ./start_rpc_server --config ${base_dir}/../executor/ir/integrated/config/distributed/server_1 &
 # start compiler service
-cd ${base_dir} && make run gremlin.script.language.name=antlr_gremlin_calcite physical.opt.config=proto graph.planner.opt=CBO graph.planner.cbo.glogue.schema=src/test/resources/statistics/modern_statistics.txt pegasus.hosts:=127.0.0.1:1234,127.0.0.1:1235 &
+cd ${base_dir} && make run gremlin.script.language.name=antlr_gremlin_calcite physical.opt.config=proto graph.planner.opt=CBO graph.statistics=./src/test/resources/statistics/modern_statistics.json pegasus.hosts:=127.0.0.1:1234,127.0.0.1:1235 &
 sleep 5s
 cd ${base_dir} && make gremlin_calcite_test
 exit_code=$?
@@ -76,7 +76,7 @@ fi
 
 # Test5: run cypher movie tests on experimental store via calcite-based ir
 # restart compiler service
-cd ${base_dir} && make run graph.schema:=../executor/ir/core/resource/movie_schema.json graph.planner.opt=CBO graph.planner.cbo.glogue.schema:=./src/main/resources/statistics/movie_statistics.txt physical.opt.config=proto graph.planner.rules=NotMatchToAntiJoinRule,FilterIntoJoinRule,FilterMatchRule,ExtendIntersectRule,ExpandGetVFusionRule &
+cd ${base_dir} && make run graph.schema:=../executor/ir/core/resource/movie_schema.json graph.planner.opt=CBO graph.statistics:=./src/main/resources/statistics/movie_statistics.json physical.opt.config=proto graph.planner.rules=NotMatchToAntiJoinRule,FilterIntoJoinRule,FilterMatchRule,ExtendIntersectRule,ExpandGetVFusionRule &
 sleep 10s
 export ENGINE_TYPE=pegasus
 cd ${base_dir} && make cypher_test
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/GraphConfig.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/GraphConfig.java
index 53226b72170c..9499a0d7bded 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/GraphConfig.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/GraphConfig.java
@@ -18,6 +18,8 @@
 
 public class GraphConfig {
     public static final Config<String> GRAPH_SCHEMA = Config.stringConfig("graph.schema", ".");
+    public static final Config<String> GRAPH_STATISTICS =
+            Config.stringConfig("graph.statistics", "");
     public static final Config<String> GRAPH_STORE = Config.stringConfig("graph.store", "exp");
 
     @Deprecated
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/PlannerConfig.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/PlannerConfig.java
index 4f9c13287af1..1512c9301353 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/PlannerConfig.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/PlannerConfig.java
@@ -1,10 +1,5 @@
 package com.alibaba.graphscope.common.config;
 
-import com.alibaba.graphscope.common.ir.rel.metadata.schema.GlogueSchema;
-
-import org.checkerframework.checker.nullness.qual.Nullable;
-
-import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
 
@@ -17,8 +12,6 @@ public class PlannerConfig {
             Config.stringConfig("graph.planner.rules", "");
     public static final Config<Integer> GRAPH_PLANNER_CBO_GLOGUE_SIZE =
             Config.intConfig("graph.planner.cbo.glogue.size", 3);
-    public static final Config<String> GRAPH_PLANNER_CBO_GLOGUE_SCHEMA =
-            Config.stringConfig("graph.planner.cbo.glogue.schema", ".");
     public static final Config<Integer> JOIN_MIN_PATTERN_SIZE =
             Config.intConfig("graph.planner.join.min.pattern.size", 5);
     public static final Config<Integer> JOIN_COST_FACTOR_1 =
@@ -28,19 +21,10 @@ public class PlannerConfig {
 
     private final Configs configs;
     private final List<String> rules;
-    private final @Nullable GlogueSchema glogueSchema;
 
     public PlannerConfig(Configs configs) {
         this.configs = configs;
         this.rules = Utils.convertDotString(GRAPH_PLANNER_RULES.get(configs));
-        try {
-            this.glogueSchema =
-                    (isOn() && getOpt() == Opt.CBO)
-                            ? GlogueSchema.fromFile(GRAPH_PLANNER_CBO_GLOGUE_SCHEMA.get(configs))
-                            : null;
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
     }
 
     public enum Opt {
@@ -64,10 +48,6 @@ public int getGlogueSize() {
         return GRAPH_PLANNER_CBO_GLOGUE_SIZE.get(configs);
     }
 
-    public @Nullable GlogueSchema getGlogueSchema() {
-        return glogueSchema;
-    }
-
     public int getJoinMinPatternSize() {
         return JOIN_MIN_PATTERN_SIZE.get(configs);
     }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/reader/LocalMetaDataReader.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/reader/LocalMetaDataReader.java
index 615234bc9371..3e9bc49e9797 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/reader/LocalMetaDataReader.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/reader/LocalMetaDataReader.java
@@ -73,4 +73,15 @@ public SchemaInputStream getGraphSchema() throws IOException {
         return new SchemaInputStream(
                 new FileInputStream(schemaPath), FileUtils.getFormatType(schemaPath));
     }
+
+    @Override
+    public SchemaInputStream getStatistics() throws Exception {
+        String statisticsPath = GraphConfig.GRAPH_STATISTICS.get(configs);
+        if (StringUtils.isEmpty(statisticsPath)) {
+            return null;
+        } else {
+            return new SchemaInputStream(
+                    new FileInputStream(statisticsPath), FileUtils.getFormatType(statisticsPath));
+        }
+    }
 }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/reader/MetaDataReader.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/reader/MetaDataReader.java
index c53a25598595..0500bf364baa 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/reader/MetaDataReader.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/reader/MetaDataReader.java
@@ -27,4 +27,6 @@ public interface MetaDataReader {
     List<InputStream> getStoredProcedures() throws Exception;
 
     SchemaInputStream getGraphSchema() throws Exception;
+
+    SchemaInputStream getStatistics() throws Exception;
 }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/IrGraphSchema.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/IrGraphSchema.java
index bdec124ad9fe..d52a9ae78e9c 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/IrGraphSchema.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/IrGraphSchema.java
@@ -110,7 +110,7 @@ public Map<GraphElement, GraphProperty> getPropertyList(int i) {
     }
 
     @Override
-    public int getVersion() {
-        return this.getVersion();
+    public String getVersion() {
+        return this.graphSchema.getVersion();
     }
 }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/IrGraphStatistics.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/IrGraphStatistics.java
new file mode 100644
index 000000000000..673de9761a00
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/IrGraphStatistics.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.common.ir.meta.schema;
+
+import com.alibaba.graphscope.common.ir.meta.reader.MetaDataReader;
+import com.alibaba.graphscope.common.ir.meta.reader.SchemaInputStream;
+import com.alibaba.graphscope.groot.common.schema.api.*;
+
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Optional;
+
+/**
+ * Maintain Graph statistics meta for IR
+ */
+public class IrGraphStatistics implements GraphStatistics {
+    private final GraphStatistics graphStatistics;
+
+    public IrGraphStatistics(MetaDataReader dataReader) throws Exception {
+        SchemaInputStream schemaInputStream = dataReader.getStatistics();
+        if (ObjectUtils.isEmpty(schemaInputStream)) {
+            this.graphStatistics = null;
+        } else {
+            String content =
+                    new String(
+                            schemaInputStream.getInputStream().readAllBytes(),
+                            StandardCharsets.UTF_8);
+            schemaInputStream.getInputStream().close();
+            this.graphStatistics = Utils.buildStatisticsFromJson(content);
+        }
+    }
+
+    public IrGraphStatistics(GraphStatistics statistics) {
+        this.graphStatistics = statistics;
+    }
+
+    @Override
+    public Long getVertexCount() {
+        return this.graphStatistics.getVertexCount();
+    }
+
+    @Override
+    public Long getEdgeCount() {
+        return this.graphStatistics.getEdgeCount();
+    }
+
+    @Override
+    public Long getVertexTypeCount(Integer vertexTypeId) {
+        return this.graphStatistics.getVertexTypeCount(vertexTypeId);
+    }
+
+    @Override
+    public Long getEdgeTypeCount(
+            Optional<Integer> sourceTypeId,
+            Optional<Integer> edgeTypeId,
+            Optional<Integer> targetTypeId) {
+        return this.graphStatistics.getEdgeTypeCount(sourceTypeId, edgeTypeId, targetTypeId);
+    }
+
+    @Override
+    public String getVersion() {
+        return this.graphStatistics.getVersion();
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/Utils.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/Utils.java
index 9bee31bec865..2d0c0d656658 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/Utils.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/meta/schema/Utils.java
@@ -19,6 +19,8 @@
 import com.alibaba.graphscope.groot.common.schema.api.*;
 import com.alibaba.graphscope.groot.common.schema.impl.*;
 import com.alibaba.graphscope.groot.common.schema.wrapper.DataType;
+import com.alibaba.graphscope.groot.common.schema.wrapper.EdgeKind;
+import com.alibaba.graphscope.groot.common.schema.wrapper.LabelId;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.ImmutableList;
@@ -264,4 +266,77 @@ public static final DataType toDataType(int ordinal) {
                         "convert from ir core type " + ordinal + " to DataType is unsupported yet");
         }
     }
+
+    /**
+     * build {@link GraphStatistics} from statistics json
+     * @param statisticsJson
+     * @return
+     */
+    public static final GraphStatistics buildStatisticsFromJson(String statisticsJson) {
+        ObjectMapper mapper = new ObjectMapper();
+        try {
+            JsonNode jsonNode = mapper.readTree(statisticsJson);
+            Map<LabelId, Long> vertexTypeCounts = Maps.newHashMap();
+            Map<EdgeKind, Long> edgeTypeCounts = Maps.newHashMap();
+            Map<String, Integer> vertexTypeNameIdMap = Maps.newHashMap();
+            Long num_vertices = jsonNode.get("total_vertex_count").asLong();
+            Long num_edges = jsonNode.get("total_edge_count").asLong();
+            JsonNode vertexTypeCountsNode = jsonNode.get("vertex_type_statistics");
+            JsonNode edgeTypeCountsNode = jsonNode.get("edge_type_statistics");
+            buildGraphElementStatisticsFromJson(
+                    vertexTypeCountsNode,
+                    "VERTEX",
+                    vertexTypeCounts,
+                    edgeTypeCounts,
+                    vertexTypeNameIdMap);
+            buildGraphElementStatisticsFromJson(
+                    edgeTypeCountsNode,
+                    "EDGE",
+                    vertexTypeCounts,
+                    edgeTypeCounts,
+                    vertexTypeNameIdMap);
+
+            return new DefaultGraphStatistics(
+                    vertexTypeCounts, edgeTypeCounts, num_vertices, num_edges);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static final void buildGraphElementStatisticsFromJson(
+            JsonNode typeCountsNode,
+            String type,
+            Map<LabelId, Long> vertexTypeCounts,
+            Map<EdgeKind, Long> edgeTypeCounts,
+            Map<String, Integer> vertexTypeNameIdMap) {
+        Iterator var1 = typeCountsNode.iterator();
+        while (var1.hasNext()) {
+            JsonNode typeStatisticJsonNode = (JsonNode) var1.next();
+            int typeId = typeStatisticJsonNode.get("type_id").asInt();
+            String typeName = typeStatisticJsonNode.get("type_name").asText();
+            if (type.equals("VERTEX")) {
+                Long typeCount = typeStatisticJsonNode.get("count").asLong();
+                vertexTypeCounts.put(new LabelId(typeId), typeCount);
+                vertexTypeNameIdMap.put(typeName, typeId);
+            } else {
+                JsonNode entityPairs = typeStatisticJsonNode.get("vertex_type_pair_statistics");
+                Iterator var2 = entityPairs.iterator();
+                while (var2.hasNext()) {
+                    JsonNode pair = (JsonNode) var2.next();
+                    String sourceLabel = pair.get("source_vertex").asText();
+                    String dstLabel = pair.get("destination_vertex").asText();
+                    Long typeCount = pair.get("count").asLong();
+                    EdgeKind edgeKind =
+                            EdgeKind.newBuilder()
+                                    .setEdgeLabelId(new LabelId(typeId))
+                                    .setSrcVertexLabelId(
+                                            new LabelId(vertexTypeNameIdMap.get(sourceLabel)))
+                                    .setDstVertexLabelId(
+                                            new LabelId(vertexTypeNameIdMap.get(dstLabel)))
+                                    .build();
+                    edgeTypeCounts.put(edgeKind, typeCount);
+                }
+            }
+        }
+    }
 }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/planner/GraphRelOptimizer.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/planner/GraphRelOptimizer.java
index 4100c8ae7c23..77b4d8289d21 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/planner/GraphRelOptimizer.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/planner/GraphRelOptimizer.java
@@ -32,6 +32,7 @@
 import com.alibaba.graphscope.common.ir.rel.metadata.schema.GlogueSchema;
 import com.alibaba.graphscope.common.ir.tools.GraphBuilderFactory;
 import com.alibaba.graphscope.common.ir.tools.config.GraphOpt;
+import com.alibaba.graphscope.common.store.IrMeta;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
@@ -87,9 +88,9 @@ public RelOptPlanner getRelPlanner() {
         return relPlanner;
     }
 
-    public @Nullable RelMetadataQuery createMetaDataQuery() {
+    public @Nullable RelMetadataQuery createMetaDataQuery(IrMeta irMeta) {
         if (config.isOn() && config.getOpt() == PlannerConfig.Opt.CBO) {
-            GlogueSchema g = config.getGlogueSchema();
+            GlogueSchema g = GlogueSchema.fromMeta(irMeta);
             Glogue gl = new Glogue(g, config.getGlogueSize());
             GlogueQuery gq = new GlogueQuery(gl);
             return new GraphRelMetadataQuery(
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/metadata/schema/GlogueSchema.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/metadata/schema/GlogueSchema.java
index 7ee1fea73abf..bd17534d7651 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/metadata/schema/GlogueSchema.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/metadata/schema/GlogueSchema.java
@@ -16,25 +16,19 @@
 
 package com.alibaba.graphscope.common.ir.rel.metadata.schema;
 
+import com.alibaba.graphscope.common.store.IrMeta;
 import com.alibaba.graphscope.groot.common.schema.api.EdgeRelation;
 import com.alibaba.graphscope.groot.common.schema.api.GraphEdge;
 import com.alibaba.graphscope.groot.common.schema.api.GraphSchema;
+import com.alibaba.graphscope.groot.common.schema.api.GraphStatistics;
 import com.alibaba.graphscope.groot.common.schema.api.GraphVertex;
-import com.alibaba.graphscope.groot.common.schema.impl.DefaultEdgeRelation;
-import com.alibaba.graphscope.groot.common.schema.impl.DefaultGraphEdge;
-import com.alibaba.graphscope.groot.common.schema.impl.DefaultGraphSchema;
-import com.alibaba.graphscope.groot.common.schema.impl.DefaultGraphVertex;
-import com.google.common.collect.Maps;
 
 import org.jgrapht.*;
 import org.jgrapht.graph.*;
 
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
+import java.util.Optional;
 
 public class GlogueSchema {
     private Graph<Integer, EdgeTypeId> schemaGraph;
@@ -62,55 +56,38 @@ public GlogueSchema(
         this.edgeTypeCardinality = edgeTypeCardinality;
     }
 
-    public static GlogueSchema fromFile(String schemaPath) throws IOException {
-        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(schemaPath))) {
-            Map<String, GraphVertex> vertexList = Maps.newHashMap();
-            Map<String, GraphEdge> edgeList = Maps.newHashMap();
-            HashMap<Integer, Double> vertexTypeCardinality = new HashMap<Integer, Double>();
-            HashMap<EdgeTypeId, Double> edgeTypeCardinality = new HashMap<EdgeTypeId, Double>();
-            String line;
-            while ((line = bufferedReader.readLine()) != null) {
-                // separate by comma
-                String[] parts = line.split(",");
-                // vertex
-                if (parts[0].equals("v")) {
-                    // v, 0, person, 3
-                    // v, 1, software, 4
-                    int labelId = Integer.parseInt(parts[1]);
-                    String label = parts[2];
-                    Double statistics = Double.parseDouble(parts[3]);
-                    DefaultGraphVertex vertex =
-                            new DefaultGraphVertex(labelId, label, List.of(), List.of(), 0, -1);
-                    vertexList.put(label, vertex);
-                    vertexTypeCardinality.put(labelId, statistics);
-                }
-                // edge
-                else if (parts[0].equals("e")) {
-                    // e, 0, knows, person, person, 5
-                    // e, 1, created, person, software, 6
-                    int labelId = Integer.parseInt(parts[1]);
-                    String label = parts[2];
-                    GraphVertex srcGraphVertex = vertexList.get(parts[3]);
-                    GraphVertex dstGraphVertex = vertexList.get(parts[4]);
-                    Double statistics = Double.parseDouble(parts[5]);
-                    int srcLabelId = srcGraphVertex.getLabelId();
-                    int dstLabelId = dstGraphVertex.getLabelId();
-                    DefaultEdgeRelation relation =
-                            new DefaultEdgeRelation(srcGraphVertex, dstGraphVertex);
-                    DefaultGraphEdge edge =
-                            new DefaultGraphEdge(labelId, label, List.of(), List.of(relation), 0);
-                    String edgeLabel = srcLabelId + label + dstLabelId;
-                    edgeList.put(edgeLabel, edge);
-                    edgeTypeCardinality.put(
-                            new EdgeTypeId(srcLabelId, dstLabelId, labelId), statistics);
-                }
+    public GlogueSchema(GraphSchema graphSchema, GraphStatistics statistics) {
+        schemaGraph = new DirectedPseudograph<Integer, EdgeTypeId>(EdgeTypeId.class);
+        vertexTypeCardinality = new HashMap<Integer, Double>();
+        edgeTypeCardinality = new HashMap<EdgeTypeId, Double>();
+        for (GraphVertex vertex : graphSchema.getVertexList()) {
+            schemaGraph.addVertex(vertex.getLabelId());
+            vertexTypeCardinality.put(
+                    vertex.getLabelId(),
+                    statistics.getVertexTypeCount(vertex.getLabelId()).doubleValue());
+        }
+        for (GraphEdge edge : graphSchema.getEdgeList()) {
+            for (EdgeRelation relation : edge.getRelationList()) {
+                int sourceType = relation.getSource().getLabelId();
+                int targetType = relation.getTarget().getLabelId();
+                EdgeTypeId edgeType = new EdgeTypeId(sourceType, targetType, edge.getLabelId());
+                schemaGraph.addEdge(sourceType, targetType, edgeType);
+                edgeTypeCardinality.put(
+                        edgeType,
+                        statistics
+                                .getEdgeTypeCount(
+                                        Optional.of(sourceType),
+                                        Optional.of(edge.getLabelId()),
+                                        Optional.of(targetType))
+                                .doubleValue());
             }
-            DefaultGraphSchema graphSchema =
-                    new DefaultGraphSchema(vertexList, edgeList, Maps.newHashMap());
-            return new GlogueSchema(graphSchema, vertexTypeCardinality, edgeTypeCardinality);
         }
     }
 
+    public static GlogueSchema fromMeta(IrMeta irMeta) {
+        return new GlogueSchema(irMeta.getSchema(), irMeta.getStatistics());
+    }
+
     public List<Integer> getVertexTypes() {
         return List.copyOf(this.schemaGraph.vertexSet());
     }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphPlanner.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphPlanner.java
index 15eaa137eb72..9b5c4a2c46e6 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphPlanner.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphPlanner.java
@@ -77,7 +77,7 @@ public GraphPlanner(Configs graphConfig, LogicalPlanFactory logicalPlanFactory)
     public PlannerInstance instance(String query, IrMeta irMeta) {
         GraphOptCluster optCluster =
                 GraphOptCluster.create(this.optimizer.getMatchPlanner(), this.rexBuilder);
-        RelMetadataQuery mq = optimizer.createMetaDataQuery();
+        RelMetadataQuery mq = optimizer.createMetaDataQuery(irMeta);
         if (mq != null) {
             optCluster.setMetadataQuerySupplier(() -> mq);
         }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/store/ExperimentalMetaFetcher.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/store/ExperimentalMetaFetcher.java
index 263fdbbfe0f2..8e241b0debab 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/store/ExperimentalMetaFetcher.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/store/ExperimentalMetaFetcher.java
@@ -19,6 +19,7 @@
 import com.alibaba.graphscope.common.ir.meta.procedure.GraphStoredProcedures;
 import com.alibaba.graphscope.common.ir.meta.reader.MetaDataReader;
 import com.alibaba.graphscope.common.ir.meta.schema.IrGraphSchema;
+import com.alibaba.graphscope.common.ir.meta.schema.IrGraphStatistics;
 
 import java.util.Optional;
 
@@ -27,7 +28,10 @@ public class ExperimentalMetaFetcher implements IrMetaFetcher {
 
     public ExperimentalMetaFetcher(MetaDataReader dataReader) throws Exception {
         this.meta =
-                new IrMeta(new IrGraphSchema(dataReader), new GraphStoredProcedures(dataReader));
+                new IrMeta(
+                        new IrGraphSchema(dataReader),
+                        new IrGraphStatistics(dataReader),
+                        new GraphStoredProcedures(dataReader));
     }
 
     @Override
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/store/IrMeta.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/store/IrMeta.java
index 5e7ecd2e64d2..043cd77b878f 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/store/IrMeta.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/store/IrMeta.java
@@ -18,6 +18,7 @@
 
 import com.alibaba.graphscope.common.ir.meta.procedure.StoredProcedures;
 import com.alibaba.graphscope.common.ir.meta.schema.IrGraphSchema;
+import com.alibaba.graphscope.groot.common.schema.api.GraphStatistics;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
@@ -27,6 +28,7 @@
 public class IrMeta {
     private final SnapshotId snapshotId;
     private final IrGraphSchema schema;
+    private final GraphStatistics statistics;
     private final @Nullable StoredProcedures storedProcedures;
 
     public IrMeta(IrGraphSchema schema) throws IOException {
@@ -37,15 +39,44 @@ public IrMeta(IrGraphSchema schema, StoredProcedures storedProcedures) {
         this(SnapshotId.createEmpty(), schema, storedProcedures);
     }
 
+    public IrMeta(
+            IrGraphSchema schema, GraphStatistics statistics, StoredProcedures storedProcedures) {
+        this(SnapshotId.createEmpty(), schema, statistics, storedProcedures);
+    }
+
+    public IrMeta(IrGraphSchema schema, GraphStatistics statistics) {
+        this(SnapshotId.createEmpty(), schema, statistics);
+    }
+
     public IrMeta(SnapshotId snapshotId, IrGraphSchema schema) throws IOException {
         this.snapshotId = Objects.requireNonNull(snapshotId);
         this.schema = Objects.requireNonNull(schema);
+        this.statistics = null;
         this.storedProcedures = null;
     }
 
     public IrMeta(SnapshotId snapshotId, IrGraphSchema schema, StoredProcedures storedProcedures) {
         this.snapshotId = Objects.requireNonNull(snapshotId);
         this.schema = Objects.requireNonNull(schema);
+        this.statistics = null;
+        this.storedProcedures = Objects.requireNonNull(storedProcedures);
+    }
+
+    public IrMeta(SnapshotId snapshotId, IrGraphSchema schema, GraphStatistics statistics) {
+        this.snapshotId = Objects.requireNonNull(snapshotId);
+        this.schema = Objects.requireNonNull(schema);
+        this.statistics = Objects.requireNonNull(statistics);
+        this.storedProcedures = null;
+    }
+
+    public IrMeta(
+            SnapshotId snapshotId,
+            IrGraphSchema schema,
+            GraphStatistics statistics,
+            StoredProcedures storedProcedures) {
+        this.snapshotId = Objects.requireNonNull(snapshotId);
+        this.schema = Objects.requireNonNull(schema);
+        this.statistics = Objects.requireNonNull(statistics);
         this.storedProcedures = Objects.requireNonNull(storedProcedures);
     }
 
@@ -60,4 +91,8 @@ public SnapshotId getSnapshotId() {
     public @Nullable StoredProcedures getStoredProcedures() {
         return storedProcedures;
     }
+
+    public GraphStatistics getStatistics() {
+        return statistics;
+    }
 }
diff --git a/interactive_engine/compiler/src/main/resources/statistics/ldbc1_statistics.json b/interactive_engine/compiler/src/main/resources/statistics/ldbc1_statistics.json
new file mode 100644
index 000000000000..fcb97467cd1f
--- /dev/null
+++ b/interactive_engine/compiler/src/main/resources/statistics/ldbc1_statistics.json
@@ -0,0 +1,301 @@
+{
+    "total_vertex_count": 2997360,
+    "total_edge_count": 17196799,
+    "vertex_type_statistics": [
+        {
+            "type_id": 3,
+            "type_name": "post",
+            "count": 1121227
+        },
+        {
+            "type_id": 2,
+            "type_name": "comment",
+            "count": 1739439
+        },
+        {
+            "type_id": 7,
+            "type_name": "tag",
+            "count": 16081
+        },
+        {
+            "type_id": 0,
+            "type_name": "place",
+            "count": 1461
+        },
+        {
+            "type_id": 4,
+            "type_name": "forum",
+            "count": 100828
+        },
+        {
+            "type_id": 6,
+            "type_name": "tagclass",
+            "count": 72
+        },
+        {
+            "type_id": 1,
+            "type_name": "person",
+            "count": 10296
+        },
+        {
+            "type_id": 5,
+            "type_name": "orgnisation",
+            "count": 7956
+        }
+    ],
+    "edge_type_statistics": [
+        {
+            "type_id": 15,
+            "type_name": "studyat",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "orgnisation",
+                    "count": 8310
+                }
+            ]
+        },
+        {
+            "type_id": 16,
+            "type_name": "workat",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "orgnisation",
+                    "count": 22045
+                }
+            ]
+        },
+        {
+            "type_id": 17,
+            "type_name": "ispartof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "place",
+                    "destination_vertex": "place",
+                    "count": 1455
+                }
+            ]
+        },
+        {
+            "type_id": 22,
+            "type_name": "issubclassof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "tagclass",
+                    "destination_vertex": "tagclass",
+                    "count": 71
+                }
+            ]
+        },
+        {
+            "type_id": 6,
+            "type_name": "hasmember",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "person",
+                    "count": 2909769
+                }
+            ]
+        },
+        {
+            "type_id": 3,
+            "type_name": "replyof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "comment",
+                    "count": 789021
+                }
+            ]
+        },
+        {
+            "type_id": 3,
+            "type_name": "replyof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "post",
+                    "count": 950419
+                }
+            ]
+        },
+        {
+            "type_id": 13,
+            "type_name": "likes",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "comment",
+                    "count": 1109814
+                }
+            ]
+        },
+        {
+            "type_id": 13,
+            "type_name": "likes",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "post",
+                    "count": 760456
+                }
+            ]
+        },
+        {
+            "type_id": 10,
+            "type_name": "hasinterest",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "tag",
+                    "count": 238053
+                }
+            ]
+        },
+        {
+            "type_id": 21,
+            "type_name": "hastype",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "tag",
+                    "destination_vertex": "tagclass",
+                    "count": 16081
+                }
+            ]
+        },
+        {
+            "type_id": 12,
+            "type_name": "knows",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "person",
+                    "count": 173015
+                }
+            ]
+        },
+        {
+            "type_id": 0,
+            "type_name": "hascreator",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "person",
+                    "count": 1739439
+                }
+            ]
+        },
+        {
+            "type_id": 0,
+            "type_name": "hascreator",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "post",
+                    "destination_vertex": "person",
+                    "count": 1121227
+                }
+            ]
+        },
+        {
+            "type_id": 5,
+            "type_name": "containerof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "post",
+                    "count": 1121227
+                }
+            ]
+        },
+        {
+            "type_id": 7,
+            "type_name": "hasmoderator",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "person",
+                    "count": 100828
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "place",
+                    "count": 10296
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "orgnisation",
+                    "destination_vertex": "place",
+                    "count": 7956
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "place",
+                    "count": 1739439
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "post",
+                    "destination_vertex": "place",
+                    "count": 1121227
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "hastag",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "tag",
+                    "count": 328585
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "hastag",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "post",
+                    "destination_vertex": "tag",
+                    "count": 751934
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "hastag",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "tag",
+                    "count": 2176132
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/interactive_engine/compiler/src/main/resources/statistics/ldbc1_statistics.txt b/interactive_engine/compiler/src/main/resources/statistics/ldbc1_statistics.txt
deleted file mode 100644
index 598b185bb1bb..000000000000
--- a/interactive_engine/compiler/src/main/resources/statistics/ldbc1_statistics.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-v,3,post,1121227
-v,2,comment,1739439
-v,7,tag,16081
-v,0,place,1461
-v,4,forum,100828
-v,6,tagclass,72
-v,1,person,10296
-v,5,orgnisation,7956
-e,15,studyat,person,orgnisation,8310
-e,16,workat,person,orgnisation,22045
-e,17,ispartof,place,place,1455
-e,22,issubclassof,tagclass,tagclass,71
-e,6,hasmember,forum,person,2909769
-e,3,replyof,comment,comment,789021
-e,3,replyof,comment,post,950419
-e,13,likes,person,comment,1109814
-e,13,likes,person,post,760456
-e,10,hasinterest,person,tag,238053
-e,21,hastype,tag,tagclass,16081
-e,12,knows,person,person,173015
-e,0,hascreator,comment,person,1739439
-e,0,hascreator,post,person,1121227
-e,5,containerof,forum,post,1121227
-e,7,hasmoderator,forum,person,100828
-e,11,islocatedin,person,place,10296
-e,11,islocatedin,orgnisation,place,7956
-e,11,islocatedin,comment,place,1739439
-e,11,islocatedin,post,place,1121227
-e,1,hastag,forum,tag,328585
-e,1,hastag,post,tag,751934
-e,1,hastag,comment,tag,2176132
\ No newline at end of file
diff --git a/interactive_engine/compiler/src/main/resources/statistics/modern_statistics.json b/interactive_engine/compiler/src/main/resources/statistics/modern_statistics.json
new file mode 100644
index 000000000000..ac3a7a7959c7
--- /dev/null
+++ b/interactive_engine/compiler/src/main/resources/statistics/modern_statistics.json
@@ -0,0 +1,40 @@
+{
+    "total_vertex_count": 6,
+    "total_edge_count": 6,
+    "vertex_type_statistics": [
+        {
+            "type_id": 0,
+            "type_name": "person", 
+            "count": 3
+        },
+        {
+            "type_id": 1,
+            "type_name": "software",
+            "count": 3
+        }
+    ],
+    "edge_type_statistics": [
+        {
+            "type_id": 0,
+            "type_name": "knows",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "person",
+                    "count": 2
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "created",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "software",
+                    "count": 4
+                }
+            ]
+        }
+    ]
+  }
\ No newline at end of file
diff --git a/interactive_engine/compiler/src/main/resources/statistics/modern_statistics.txt b/interactive_engine/compiler/src/main/resources/statistics/modern_statistics.txt
deleted file mode 100644
index f77f4583de25..000000000000
--- a/interactive_engine/compiler/src/main/resources/statistics/modern_statistics.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-v,0,person,3
-v,1,software,4
-e,0,knows,person,person,5
-e,1,created,person,software,6
\ No newline at end of file
diff --git a/interactive_engine/compiler/src/main/resources/statistics/movie_statistics.json b/interactive_engine/compiler/src/main/resources/statistics/movie_statistics.json
new file mode 100644
index 000000000000..a3ae5ea7b943
--- /dev/null
+++ b/interactive_engine/compiler/src/main/resources/statistics/movie_statistics.json
@@ -0,0 +1,89 @@
+{
+    "total_vertex_count": 175,
+    "total_edge_count": 265,
+    "vertex_type_statistics": [
+        {
+            "type_id": 0,
+            "type_name": "movie",
+            "count": 38
+        },
+        {
+            "type_id": 1,
+            "type_name": "person",
+            "count": 130
+        },
+        {
+            "type_id": 2,
+            "type_name": "user",
+            "count": 7
+        }
+    ],
+    "edge_type_statistics": [
+        {
+            "type_id": 0,
+            "type_name": "acted_in",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "movie",
+                    "count": 172
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "directed",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "movie",
+                    "count": 44
+                }
+            ]
+        },
+        {
+            "type_id": 2,
+            "type_name": "review",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "user",
+                    "destination_vertex": "movie",
+                    "count": 16
+                }
+            ]
+        },
+        {
+            "type_id": 3,
+            "type_name": "follows",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "user",
+                    "destination_vertex": "person",
+                    "count": 8
+                }
+            ]
+        },
+        {
+            "type_id": 4,
+            "type_name": "wrote",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "movie",
+                    "count": 10
+                }
+            ]
+        },
+        {
+            "type_id": 5,
+            "type_name": "produced",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "movie",
+                    "count": 15
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/interactive_engine/compiler/src/main/resources/statistics/movie_statistics.txt b/interactive_engine/compiler/src/main/resources/statistics/movie_statistics.txt
deleted file mode 100644
index ff2b2a3d2229..000000000000
--- a/interactive_engine/compiler/src/main/resources/statistics/movie_statistics.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-v,0,movie,38
-v,1,person,130
-v,2,user,7
-e,0,acted_in,person,movie,172
-e,1,directed,person,movie,44
-e,2,review,user,movie,16
-e,3,follows,user,person,8
-e,4,wrote,person,movie,10
-e,5,produced,person,movie,15
\ No newline at end of file
diff --git a/interactive_engine/frontend/src/main/java/com/alibaba/graphscope/frontend/VineyardMetaFetcher.java b/interactive_engine/frontend/src/main/java/com/alibaba/graphscope/frontend/VineyardMetaFetcher.java
index 7d5162b4c257..5626887359d1 100644
--- a/interactive_engine/frontend/src/main/java/com/alibaba/graphscope/frontend/VineyardMetaFetcher.java
+++ b/interactive_engine/frontend/src/main/java/com/alibaba/graphscope/frontend/VineyardMetaFetcher.java
@@ -33,6 +33,7 @@ public VineyardMetaFetcher(String schemaPath) {
         JsonFileSchemaFetcher fetcher = new JsonFileSchemaFetcher(schemaPath);
         GraphSchema graphSchema = fetcher.getSchemaSnapshotPair().values().iterator().next();
         try {
+            // TODO: support statistics, otherwise, the CBO will not work
             this.irMeta = new IrMeta(new IrGraphSchema(graphSchema, true));
         } catch (IOException e) {
             throw new RuntimeException(e);
diff --git a/interactive_engine/groot-module/src/main/java/com/alibaba/graphscope/groot/SnapshotCache.java b/interactive_engine/groot-module/src/main/java/com/alibaba/graphscope/groot/SnapshotCache.java
index f27740bb61ec..365e860ba228 100644
--- a/interactive_engine/groot-module/src/main/java/com/alibaba/graphscope/groot/SnapshotCache.java
+++ b/interactive_engine/groot-module/src/main/java/com/alibaba/graphscope/groot/SnapshotCache.java
@@ -89,7 +89,8 @@ public synchronized long advanceQuerySnapshotId(long snapshotId, GraphDef graphD
         GraphDef oldGraphDef = snapshotWithSchema.getGraphDef();
         if (graphDef != null
                 && (oldGraphDef == null
-                        || graphDef.getSchemaVersion() > oldGraphDef.getVersion())) {
+                        || graphDef.getSchemaVersion()
+                                > Long.parseLong(oldGraphDef.getVersion()))) {
             newSnapshotInfoBuilder.setGraphDef(graphDef);
             logger.info("schema updated. schema version [" + graphDef.getVersion() + "]");
             logger.debug(graphDef.toProto().toString());
diff --git a/interactive_engine/groot-module/src/main/java/com/alibaba/graphscope/groot/frontend/GrootDdlService.java b/interactive_engine/groot-module/src/main/java/com/alibaba/graphscope/groot/frontend/GrootDdlService.java
index f4f34719c409..865199281796 100644
--- a/interactive_engine/groot-module/src/main/java/com/alibaba/graphscope/groot/frontend/GrootDdlService.java
+++ b/interactive_engine/groot-module/src/main/java/com/alibaba/graphscope/groot/frontend/GrootDdlService.java
@@ -145,7 +145,7 @@ public void batchSubmit(
 
     private GraphDefPb toGraphDefPb(GraphDef graphDef) {
         GraphDefPb.Builder builder = GraphDefPb.newBuilder();
-        builder.setVersion(graphDef.getVersion());
+        builder.setVersion(Integer.parseInt(graphDef.getVersion()));
         builder.setKey("");
         builder.setGraphType(GraphTypePb.PERSISTENT_STORE);
         builder.setDirected(true);
diff --git a/interactive_engine/groot-server/src/main/java/com/alibaba/graphscope/groot/servers/ir/GrootMetaFetcher.java b/interactive_engine/groot-server/src/main/java/com/alibaba/graphscope/groot/servers/ir/GrootMetaFetcher.java
index 6a77d0f824da..4fbbf90353bc 100644
--- a/interactive_engine/groot-server/src/main/java/com/alibaba/graphscope/groot/servers/ir/GrootMetaFetcher.java
+++ b/interactive_engine/groot-server/src/main/java/com/alibaba/graphscope/groot/servers/ir/GrootMetaFetcher.java
@@ -43,6 +43,7 @@ public Optional<IrMeta> fetch() {
             GraphSchema schema = entry.getValue();
 
             try {
+                // TODO: add statistics, otherwise, the CBO will not work
                 return Optional.of(
                         new IrMeta(
                                 new SnapshotId(true, snapshotId), new IrGraphSchema(schema, true)));


Test patch:
diff --git a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/Utils.java b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/Utils.java
index 021a778e1ebb..b3a9451f0287 100644
--- a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/Utils.java
+++ b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/Utils.java
@@ -71,7 +71,7 @@ public static final GraphBuilder mockGraphBuilder(String schemaJson) {
     public static final GraphBuilder mockGraphBuilder(GraphRelOptimizer optimizer, IrMeta irMeta) {
         RelOptCluster optCluster =
                 GraphOptCluster.create(optimizer.getMatchPlanner(), Utils.rexBuilder);
-        optCluster.setMetadataQuerySupplier(() -> optimizer.createMetaDataQuery());
+        optCluster.setMetadataQuerySupplier(() -> optimizer.createMetaDataQuery(irMeta));
         return (GraphBuilder)
                 relBuilderFactory.create(
                         optCluster, new GraphOptSchema(optCluster, irMeta.getSchema()));
@@ -98,6 +98,10 @@ public static IrMeta mockSchemaMeta(String schemaJson) {
         try {
             URL schemaResource =
                     Thread.currentThread().getContextClassLoader().getResource(schemaJson);
+            URL statisticsResource =
+                    Thread.currentThread()
+                            .getContextClassLoader()
+                            .getResource("statistics/modern_statistics.json");
             String yamlStr = FileUtils.readJsonFromResource("config/modern/graph.yaml");
             Yaml yaml = new Yaml();
             Map<String, Object> yamlMap = yaml.load(yamlStr);
@@ -107,6 +111,33 @@ public static IrMeta mockSchemaMeta(String schemaJson) {
                             ImmutableMap.of(
                                     GraphConfig.GRAPH_SCHEMA.getKey(),
                                     schemaResource.toURI().getPath(),
+                                    GraphConfig.GRAPH_STATISTICS.getKey(),
+                                    statisticsResource.toURI().getPath(),
+                                    GraphConfig.GRAPH_STORED_PROCEDURES_YAML.getKey(),
+                                    proceduresYaml));
+            return new ExperimentalMetaFetcher(new LocalMetaDataReader(configs)).fetch().get();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static IrMeta mockIrMeta(String schemaJson, String statisticsJson) {
+        try {
+            URL schemaResource =
+                    Thread.currentThread().getContextClassLoader().getResource(schemaJson);
+            URL statisticsResource =
+                    Thread.currentThread().getContextClassLoader().getResource(statisticsJson);
+            String yamlStr = FileUtils.readJsonFromResource("config/modern/graph.yaml");
+            Yaml yaml = new Yaml();
+            Map<String, Object> yamlMap = yaml.load(yamlStr);
+            String proceduresYaml = yaml.dump(yamlMap.get("stored_procedures"));
+            Configs configs =
+                    new Configs(
+                            ImmutableMap.of(
+                                    GraphConfig.GRAPH_SCHEMA.getKey(),
+                                    schemaResource.toURI().getPath(),
+                                    GraphConfig.GRAPH_STATISTICS.getKey(),
+                                    statisticsResource.toURI().getPath(),
                                     GraphConfig.GRAPH_STORED_PROCEDURES_YAML.getKey(),
                                     proceduresYaml));
             return new ExperimentalMetaFetcher(new LocalMetaDataReader(configs)).fetch().get();
diff --git a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/BITest.java b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/BITest.java
index bb37097c34ce..c5a2bac7c2ee 100644
--- a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/BITest.java
+++ b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/BITest.java
@@ -47,11 +47,12 @@ public static void beforeClass() {
                                 "CBO",
                                 "graph.planner.rules",
                                 "FilterIntoJoinRule, FilterMatchRule,"
-                                        + " ExtendIntersectRule, ExpandGetVFusionRule",
-                                "graph.planner.cbo.glogue.schema",
-                                "target/test-classes/statistics/ldbc30_hierarchy_statistics.txt"));
+                                        + " ExtendIntersectRule, ExpandGetVFusionRule"));
         optimizer = new GraphRelOptimizer(configs);
-        irMeta = Utils.mockSchemaMeta("schema/ldbc_schema_exp_hierarchy.json");
+        irMeta =
+                Utils.mockIrMeta(
+                        "schema/ldbc_schema_exp_hierarchy.json",
+                        "statistics/ldbc30_hierarchy_statistics.json");
     }
 
     @Test
diff --git a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/CBOTest.java b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/CBOTest.java
index 2b15b71988be..8e4ff6be26c6 100644
--- a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/CBOTest.java
+++ b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/CBOTest.java
@@ -29,11 +29,12 @@ public static void beforeClass() {
                                 "CBO",
                                 "graph.planner.rules",
                                 "FilterIntoJoinRule, FilterMatchRule, ExtendIntersectRule,"
-                                        + " ExpandGetVFusionRule",
-                                "graph.planner.cbo.glogue.schema",
-                                "target/test-classes/statistics/ldbc30_hierarchy_statistics.txt"));
+                                        + " ExpandGetVFusionRule"));
         optimizer = new GraphRelOptimizer(configs);
-        irMeta = Utils.mockSchemaMeta("schema/ldbc_schema_exp_hierarchy.json");
+        irMeta =
+                Utils.mockIrMeta(
+                        "schema/ldbc_schema_exp_hierarchy.json",
+                        "statistics/ldbc30_hierarchy_statistics.json");
     }
 
     @Test
diff --git a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/LdbcTest.java b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/LdbcTest.java
index 9a0e9db8c622..73ea2d1a408a 100644
--- a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/LdbcTest.java
+++ b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/LdbcTest.java
@@ -29,11 +29,9 @@ public static void beforeClass() {
                                 "CBO",
                                 "graph.planner.rules",
                                 "NotMatchToAntiJoinRule, FilterIntoJoinRule, FilterMatchRule,"
-                                        + " ExtendIntersectRule, ExpandGetVFusionRule",
-                                "graph.planner.cbo.glogue.schema",
-                                "target/test-classes/statistics/ldbc30_statistics.txt"));
+                                        + " ExtendIntersectRule, ExpandGetVFusionRule"));
         optimizer = new GraphRelOptimizer(configs);
-        irMeta = Utils.mockSchemaMeta("schema/ldbc.json");
+        irMeta = Utils.mockIrMeta("schema/ldbc.json", "statistics/ldbc30_statistics.json");
     }
 
     @Test
diff --git a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/STPathTest.java b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/STPathTest.java
index 97a3c4f5a37b..32b79316e36d 100644
--- a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/STPathTest.java
+++ b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/planner/cbo/STPathTest.java
@@ -53,11 +53,9 @@ public static void beforeClass() {
                                 "graph.planner.rules",
                                 "NotMatchToAntiJoinRule, FilterIntoJoinRule, FilterMatchRule,"
                                         + " ExtendIntersectRule, JoinDecompositionRule,"
-                                        + " ExpandGetVFusionRule",
-                                "graph.planner.cbo.glogue.schema",
-                                "target/test-classes/statistics/ldbc30_statistics.txt"));
+                                        + " ExpandGetVFusionRule"));
         optimizer = new GraphRelOptimizer(configs);
-        irMeta = Utils.mockSchemaMeta("schema/ldbc.json");
+        irMeta = Utils.mockIrMeta("schema/ldbc.json", "statistics/ldbc30_statistics.json");
     }
 
     @Test
diff --git a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/runtime/GraphRelToProtoTest.java b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/runtime/GraphRelToProtoTest.java
index 3fe7ce8e4e40..7ad5b8228796 100644
--- a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/runtime/GraphRelToProtoTest.java
+++ b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/common/ir/runtime/GraphRelToProtoTest.java
@@ -1203,9 +1203,7 @@ private Configs getMockCBOConfig() {
                         "CBO",
                         "graph.planner.rules",
                         "FilterIntoJoinRule, FilterMatchRule, ExtendIntersectRule,"
-                                + " ExpandGetVFusionRule",
-                        "graph.planner.cbo.glogue.schema",
-                        "target/test-classes/statistics/ldbc30_hierarchy_statistics.txt"));
+                                + " ExpandGetVFusionRule"));
     }
 
     private Configs getMockPartitionedCBOConfig() {
@@ -1218,8 +1216,6 @@ private Configs getMockPartitionedCBOConfig() {
                         "graph.planner.rules",
                         "FilterIntoJoinRule, FilterMatchRule, ExtendIntersectRule,"
                                 + " ExpandGetVFusionRule",
-                        "graph.planner.cbo.glogue.schema",
-                        "target/test-classes/statistics/ldbc30_hierarchy_statistics.txt",
                         "pegasus.hosts",
                         "host1,host2"));
     }
@@ -1229,7 +1225,9 @@ private GraphRelOptimizer getMockCBO() {
     }
 
     private IrMeta getMockCBOMeta() {
-        return Utils.mockSchemaMeta("schema/ldbc_schema_exp_hierarchy.json");
+        return Utils.mockIrMeta(
+                "schema/ldbc_schema_exp_hierarchy.json",
+                "statistics/ldbc30_hierarchy_statistics.json");
     }
 
     private Configs getMockGraphConfig() {
diff --git a/interactive_engine/compiler/src/test/resources/statistics/ldbc30_hierarchy_statistics.json b/interactive_engine/compiler/src/test/resources/statistics/ldbc30_hierarchy_statistics.json
new file mode 100644
index 000000000000..b0d31d1eb28d
--- /dev/null
+++ b/interactive_engine/compiler/src/test/resources/statistics/ldbc30_hierarchy_statistics.json
@@ -0,0 +1,348 @@
+{
+    "total_vertex_count": 78244715,
+    "total_edge_count": 505722382,
+    "vertex_type_statistics": [
+        {
+            "type_id": 3,
+            "type_name": "post",
+            "count": 21651343
+        },
+        {
+            "type_id": 2,
+            "type_name": "comment",
+            "count": 54737516
+        },
+        {
+            "type_id": 7,
+            "type_name": "tag",
+            "count": 16081
+        },
+        {
+            "type_id": 9,
+            "type_name": "city",
+            "count": 1343
+        },
+        {
+            "type_id": 8,
+            "type_name": "country",
+            "count": 111
+        },
+        {
+            "type_id": 10,
+            "type_name": "continent",
+            "count": 6
+        },
+        {
+            "type_id": 4,
+            "type_name": "forum",
+            "count": 1659633
+        },
+        {
+            "type_id": 5,
+            "type_name": "orgnisation",
+            "count": 7956
+        },
+        {
+            "type_id": 0,
+            "type_name": "place",
+            "count": 1461
+        },
+        {
+            "type_id": 6,
+            "type_name": "tagclass",
+            "count": 72
+        },
+        {
+            "type_id": 1,
+            "type_name": "person",
+            "count": 170655
+        },
+        {
+            "type_id": 11,
+            "type_name": "company",
+            "count": 1575
+        },
+        {
+            "type_id": 12,
+            "type_name": "university",
+            "count": 6380
+        }
+    ],
+    "edge_type_statistics": [
+        {
+            "type_id": 15,
+            "type_name": "studyat",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "university",
+                    "count": 136615
+                }
+            ]
+        },
+        {
+            "type_id": 16,
+            "type_name": "workat",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "company",
+                    "count": 371635
+                }
+            ]
+        },
+        {
+            "type_id": 17,
+            "type_name": "ispartof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "city",
+                    "destination_vertex": "country",
+                    "count": 1343
+                }
+            ]
+        },
+        {
+            "type_id": 17,
+            "type_name": "ispartof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "country",
+                    "destination_vertex": "continent",
+                    "count": 111
+                }
+            ]
+        },
+        {
+            "type_id": 22,
+            "type_name": "issubclassof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "tagclass",
+                    "destination_vertex": "tagclass",
+                    "count": 71
+                }
+            ]
+        },
+        {
+            "type_id": 6,
+            "type_name": "hasmember",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "person",
+                    "count": 90198119
+                }
+            ]
+        },
+        {
+            "type_id": 3,
+            "type_name": "replyof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "comment",
+                    "count": 25130259
+                }
+            ]
+        },
+        {
+            "type_id": 3,
+            "type_name": "replyof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "post",
+                    "count": 29607258
+                }
+            ]
+        },
+        {
+            "type_id": 13,
+            "type_name": "likes",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "comment",
+                    "count": 48651550
+                }
+            ]
+        },
+        {
+            "type_id": 13,
+            "type_name": "likes",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "post",
+                    "count": 26908835
+                }
+            ]
+        },
+        {
+            "type_id": 10,
+            "type_name": "hasinterest",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "tag",
+                    "count": 3978965
+                }
+            ]
+        },
+        {
+            "type_id": 21,
+            "type_name": "hastype",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "tag",
+                    "destination_vertex": "tagclass",
+                    "count": 16081
+                }
+            ]
+        },
+        {
+            "type_id": 12,
+            "type_name": "knows",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "person",
+                    "count": 5524303
+                }
+            ]
+        },
+        {
+            "type_id": 0,
+            "type_name": "hascreator",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "person",
+                    "count": 54737516
+                }
+            ]
+        },
+        {
+            "type_id": 0,
+            "type_name": "hascreator",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "post",
+                    "destination_vertex": "person",
+                    "count": 21651343
+                }
+            ]
+        },
+        {
+            "type_id": 5,
+            "type_name": "containerof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "post",
+                    "count": 21651343
+                }
+            ]
+        },
+        {
+            "type_id": 7,
+            "type_name": "hasmoderator",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "person",
+                    "count": 1659633
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "city",
+                    "count": 170655
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "company",
+                    "destination_vertex": "country",
+                    "count": 1575
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "university",
+                    "destination_vertex": "city",
+                    "count": 6380
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "country",
+                    "count": 54737516
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "post",
+                    "destination_vertex": "country",
+                    "count": 21651343
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "hastag",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "tag",
+                    "count": 5467943
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "hastag",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "post",
+                    "destination_vertex": "tag",
+                    "count": 23426339
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "hastag",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "tag",
+                    "count": 70035651
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/interactive_engine/compiler/src/test/resources/statistics/ldbc30_hierarchy_statistics.txt b/interactive_engine/compiler/src/test/resources/statistics/ldbc30_hierarchy_statistics.txt
deleted file mode 100644
index 497e0775a582..000000000000
--- a/interactive_engine/compiler/src/test/resources/statistics/ldbc30_hierarchy_statistics.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-v,3,post,21651343
-v,2,comment,54737516
-v,7,tag,16081
-v,9,city,1343
-v,8,country,111
-v,10,continent,6
-v,4,forum,1659633
-v,6,tagclass,72
-v,1,person,170655
-v,11,company, 1575
-v,12,university,6380
-e,15,studyat,person,university,136615
-e,16,workat,person,company,371635
-e,17,ispartof,city,country,1343
-e,17,ispartof,country,continent,111
-e,22,issubclassof,tagclass,tagclass,71
-e,6,hasmember,forum,person,90198119
-e,3,replyof,comment,comment,25130259
-e,3,replyof,comment,post,29607258
-e,13,likes,person,comment,48651550
-e,13,likes,person,post,26908835
-e,10,hasinterest,person,tag,3978965
-e,21,hastype,tag,tagclass,16081
-e,12,knows,person,person,5524303
-e,0,hascreator,comment,person,54737516
-e,0,hascreator,post,person,21651343
-e,5,containerof,forum,post,21651343
-e,7,hasmoderator,forum,person,1659633
-e,11,islocatedin,person,city,170655
-e,11,islocatedin,company,country,1575
-e,11,islocatedin,university,city,6380
-e,11,islocatedin,comment,country,54737516
-e,11,islocatedin,post,country,21651343
-e,1,hastag,forum,tag,5467943
-e,1,hastag,post,tag,23426339
-e,1,hastag,comment,tag,70035651
\ No newline at end of file
diff --git a/interactive_engine/compiler/src/test/resources/statistics/ldbc30_statistics.json b/interactive_engine/compiler/src/test/resources/statistics/ldbc30_statistics.json
new file mode 100644
index 000000000000..ca1203d1baaa
--- /dev/null
+++ b/interactive_engine/compiler/src/test/resources/statistics/ldbc30_statistics.json
@@ -0,0 +1,301 @@
+{
+    "total_vertex_count": 78244717,
+    "total_edge_count": 505722384,
+    "vertex_type_statistics": [
+        {
+            "type_id": 3,
+            "type_name": "post",
+            "count": 21651343
+        },
+        {
+            "type_id": 2,
+            "type_name": "comment",
+            "count": 54737516
+        },
+        {
+            "type_id": 7,
+            "type_name": "tag",
+            "count": 16081
+        },
+        {
+            "type_id": 0,
+            "type_name": "place",
+            "count": 1461
+        },
+        {
+            "type_id": 4,
+            "type_name": "forum",
+            "count": 1659633
+        },
+        {
+            "type_id": 6,
+            "type_name": "tagclass",
+            "count": 72
+        },
+        {
+            "type_id": 1,
+            "type_name": "person",
+            "count": 170655
+        },
+        {
+            "type_id": 5,
+            "type_name": "orgnisation",
+            "count": 7956
+        }
+    ],
+    "edge_type_statistics": [
+        {
+            "type_id": 15,
+            "type_name": "studyat",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "orgnisation",
+                    "count": 136615
+                }
+            ]
+        },
+        {
+            "type_id": 16,
+            "type_name": "workat",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "orgnisation",
+                    "count": 371635
+                }
+            ]
+        },
+        {
+            "type_id": 17,
+            "type_name": "ispartof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "place",
+                    "destination_vertex": "place",
+                    "count": 1455
+                }
+            ]
+        },
+        {
+            "type_id": 22,
+            "type_name": "issubclassof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "tagclass",
+                    "destination_vertex": "tagclass",
+                    "count": 71
+                }
+            ]
+        },
+        {
+            "type_id": 6,
+            "type_name": "hasmember",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "person",
+                    "count": 90198119
+                }
+            ]
+        },
+        {
+            "type_id": 3,
+            "type_name": "replyof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "comment",
+                    "count": 25130259
+                }
+            ]
+        },
+        {
+            "type_id": 3,
+            "type_name": "replyof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "post",
+                    "count": 29607258
+                }
+            ]
+        },
+        {
+            "type_id": 13,
+            "type_name": "likes",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "comment",
+                    "count": 48651550
+                }
+            ]
+        },
+        {
+            "type_id": 13,
+            "type_name": "likes",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "post",
+                    "count": 26908835
+                }
+            ]
+        },
+        {
+            "type_id": 10,
+            "type_name": "hasinterest",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "tag",
+                    "count": 3978965
+                }
+            ]
+        },
+        {
+            "type_id": 21,
+            "type_name": "hastype",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "tag",
+                    "destination_vertex": "tagclass",
+                    "count": 16081
+                }
+            ]
+        },
+        {
+            "type_id": 12,
+            "type_name": "knows",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "person",
+                    "count": 5524303
+                }
+            ]
+        },
+        {
+            "type_id": 0,
+            "type_name": "hascreator",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "person",
+                    "count": 54737516
+                }
+            ]
+        },
+        {
+            "type_id": 0,
+            "type_name": "hascreator",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "post",
+                    "destination_vertex": "person",
+                    "count": 21651343
+                }
+            ]
+        },
+        {
+            "type_id": 5,
+            "type_name": "containerof",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "post",
+                    "count": 21651343
+                }
+            ]
+        },
+        {
+            "type_id": 7,
+            "type_name": "hasmoderator",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "person",
+                    "count": 1659633
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "place",
+                    "count": 170655
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "orgnisation",
+                    "destination_vertex": "place",
+                    "count": 7956
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "place",
+                    "count": 54737516
+                }
+            ]
+        },
+        {
+            "type_id": 11,
+            "type_name": "islocatedin",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "post",
+                    "destination_vertex": "place",
+                    "count": 21651343
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "hastag",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "forum",
+                    "destination_vertex": "tag",
+                    "count": 5467943
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "hastag",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "post",
+                    "destination_vertex": "tag",
+                    "count": 23426339
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "hastag",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "comment",
+                    "destination_vertex": "tag",
+                    "count": 70035651
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/interactive_engine/compiler/src/test/resources/statistics/ldbc30_statistics.txt b/interactive_engine/compiler/src/test/resources/statistics/ldbc30_statistics.txt
deleted file mode 100644
index 5bd541669b23..000000000000
--- a/interactive_engine/compiler/src/test/resources/statistics/ldbc30_statistics.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-v,3,post,21651343
-v,2,comment,54737516
-v,7,tag,16081
-v,0,place,1461
-v,4,forum,1659633
-v,6,tagclass,72
-v,1,person,170655
-v,5,orgnisation,7956
-e,15,studyat,person,orgnisation,136615
-e,16,workat,person,orgnisation,371635
-e,17,ispartof,place,place,1455
-e,22,issubclassof,tagclass,tagclass,71
-e,6,hasmember,forum,person,90198119
-e,3,replyof,comment,comment,25130259
-e,3,replyof,comment,post,29607258
-e,13,likes,person,comment,48651550
-e,13,likes,person,post,26908835
-e,10,hasinterest,person,tag,3978965
-e,21,hastype,tag,tagclass,16081
-e,12,knows,person,person,5524303
-e,0,hascreator,comment,person,54737516
-e,0,hascreator,post,person,21651343
-e,5,containerof,forum,post,21651343
-e,7,hasmoderator,forum,person,1659633
-e,11,islocatedin,person,place,170655
-e,11,islocatedin,orgnisation,place,7956
-e,11,islocatedin,comment,place,54737516
-e,11,islocatedin,post,place,21651343
-e,1,hastag,forum,tag,5467943
-e,1,hastag,post,tag,23426339
-e,1,hastag,comment,tag,70035651
\ No newline at end of file
diff --git a/interactive_engine/compiler/src/test/resources/statistics/modern_statistics.json b/interactive_engine/compiler/src/test/resources/statistics/modern_statistics.json
new file mode 100644
index 000000000000..ac3a7a7959c7
--- /dev/null
+++ b/interactive_engine/compiler/src/test/resources/statistics/modern_statistics.json
@@ -0,0 +1,40 @@
+{
+    "total_vertex_count": 6,
+    "total_edge_count": 6,
+    "vertex_type_statistics": [
+        {
+            "type_id": 0,
+            "type_name": "person", 
+            "count": 3
+        },
+        {
+            "type_id": 1,
+            "type_name": "software",
+            "count": 3
+        }
+    ],
+    "edge_type_statistics": [
+        {
+            "type_id": 0,
+            "type_name": "knows",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "person",
+                    "count": 2
+                }
+            ]
+        },
+        {
+            "type_id": 1,
+            "type_name": "created",
+            "vertex_type_pair_statistics": [
+                {
+                    "source_vertex": "person",
+                    "destination_vertex": "software",
+                    "count": 4
+                }
+            ]
+        }
+    ]
+  }
\ No newline at end of file
diff --git a/interactive_engine/compiler/src/test/resources/statistics/modern_statistics.txt b/interactive_engine/compiler/src/test/resources/statistics/modern_statistics.txt
deleted file mode 100644
index c49aafa9283c..000000000000
--- a/interactive_engine/compiler/src/test/resources/statistics/modern_statistics.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-v,1,software,2
-v,0,person,4
-e,0,knows,person,person,2
-e,1,created,person,software,4
\ No newline at end of file