From 23d3c634341f12da8ad1d22c5236d75fb558426c Mon Sep 17 00:00:00 2001 From: Karol Sobczak Date: Fri, 23 Sep 2022 13:05:10 +0200 Subject: [PATCH 1/2] Show local cost in EXPLAIN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/trinodb/trino/commit/e438e1ef8becdf84c320b07615b1f99e915e2b19 changed cost calculations to be cumulative. However, EXPLAIN still used PlanCostEstimate for showing plan node cost. This commit makes EXPLAIN use local cost. after (take a look at Aggregate operator cpu cost): trino> explain select count(orderkey) from hive.tpch_sf10_orc.lineitem; Query Plan --------------------------------------------------------------------------------------- Fragment 0 [SINGLE] Output layout: [count] Output partitioning: SINGLE [] Output[columnNames = [_col0]] │ Layout: [count:bigint] │ Estimates: {rows: 1 (9B), cpu: 0, memory: 0B, network: 0B} │ _col0 := count └─ Aggregate[] │ Layout: [count:bigint] │ Estimates: {rows: 1 (9B), cpu: 514.86M, memory: 9B, network: 0B} │ count := count("orderkey") └─ LocalExchange[partitioning = SINGLE] │ Layout: [orderkey:bigint] │ Estimates: {rows: 59986052 (514.86MB), cpu: 0, memory: 0B, network: 0B} └─ RemoteSource[sourceFragmentIds = [1]] Layout: [orderkey:bigint] Estimates: Fragment 1 [SOURCE] Output layout: [orderkey] Output partitioning: SINGLE [] TableScan[table = hive:tpch_sf10_orc:lineitem] Layout: [orderkey:bigint] Estimates: {rows: 59986052 (514.86MB), cpu: 514.86M, memory: 0B, network: 0B} orderkey := orderkey:bigint:REGULAR before: trino> explain select count(orderkey) from hive.tpch_sf10_orc.lineitem; Query Plan --------------------------------------------------------------------------------------------------- Fragment 0 [SINGLE] Output layout: [count] Output partitioning: SINGLE [] Output[columnNames = [_col0]] │ Layout: [count:bigint] │ Estimates: {rows: 1 (9B), cpu: 1.01G, memory: 9B, network: 514.86MB} │ _col0 := count └─ Aggregate[] │ Layout: [count:bigint] │ Estimates: {rows: 1 (9B), cpu: 1.01G, memory: 9B, network: 514.86MB} │ count := count("orderkey") └─ LocalExchange[partitioning = SINGLE] │ Layout: [orderkey:bigint] │ Estimates: {rows: 59986052 (514.86MB), cpu: 514.86M, memory: 0B, network: 514.86MB} └─ RemoteSource[sourceFragmentIds = [1]] Layout: [orderkey:bigint] Estimates: Fragment 1 [SOURCE] Output layout: [orderkey] Output partitioning: SINGLE [] TableScan[table = hive:tpch_sf10_orc:lineitem] Layout: [orderkey:bigint] Estimates: {rows: 59986052 (514.86MB), cpu: 514.86M, memory: 0B, network: 0B} orderkey := orderkey:bigint:REGULAR --- .../planner/planprinter/NodeRepresentation.java | 5 +++-- .../planprinter/TestJsonRepresentation.java | 16 ++++++++-------- .../java/io/trino/tests/TestLocalQueries.java | 1 + 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/NodeRepresentation.java b/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/NodeRepresentation.java index 42bca29b93f5..3e7a61619e63 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/NodeRepresentation.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/NodeRepresentation.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.ImmutableList; +import io.trino.cost.LocalCostEstimate; import io.trino.cost.PlanCostEstimate; import io.trino.cost.PlanNodeStatsAndCostSummary; import io.trino.cost.PlanNodeStatsEstimate; @@ -151,14 +152,14 @@ public Optional getReorderJoinStatsAndCost() public List getEstimates(TypeProvider typeProvider) { if (getEstimatedStats().stream().allMatch(PlanNodeStatsEstimate::isOutputRowCountUnknown) && - getEstimatedCost().stream().allMatch(c -> c.equals(PlanCostEstimate.unknown()))) { + getEstimatedCost().stream().allMatch(c -> c.getRootNodeLocalCostEstimate().equals(LocalCostEstimate.unknown()))) { return ImmutableList.of(); } ImmutableList.Builder estimates = ImmutableList.builder(); for (int i = 0; i < getEstimatedStats().size(); i++) { PlanNodeStatsEstimate stats = getEstimatedStats().get(i); - PlanCostEstimate cost = getEstimatedCost().get(i); + LocalCostEstimate cost = getEstimatedCost().get(i).getRootNodeLocalCostEstimate(); List outputSymbols = getOutputs().stream() .map(NodeRepresentation.TypedSymbol::getSymbol) diff --git a/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestJsonRepresentation.java b/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestJsonRepresentation.java index 572977ba65bd..2de5cbef3360 100644 --- a/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestJsonRepresentation.java +++ b/core/trino-main/src/test/java/io/trino/sql/planner/planprinter/TestJsonRepresentation.java @@ -84,14 +84,14 @@ public void testDistributedJsonPlan() ImmutableMap.of("columnNames", "[quantity]"), ImmutableList.of(typedSymbol("quantity", "double")), ImmutableList.of(), - ImmutableList.of(new PlanNodeStatsAndCostSummary(10, 90, 541665, 0, 0)), + ImmutableList.of(new PlanNodeStatsAndCostSummary(10, 90, 0, 0, 0)), ImmutableList.of(new JsonRenderedNode( "98", "Limit", ImmutableMap.of("count", "10", "withTies", "", "inputPreSortedBy", "[]"), ImmutableList.of(typedSymbol("quantity", "double")), ImmutableList.of(), - ImmutableList.of(new PlanNodeStatsAndCostSummary(10, 90, 541665, 0, 0)), + ImmutableList.of(new PlanNodeStatsAndCostSummary(10, 90, 90, 0, 0)), ImmutableList.of(new JsonRenderedNode( "147", "LocalExchange", @@ -102,7 +102,7 @@ public void testDistributedJsonPlan() "arguments", "[]"), ImmutableList.of(typedSymbol("quantity", "double")), ImmutableList.of(), - ImmutableList.of(new PlanNodeStatsAndCostSummary(60175, 541575, 541575, 0, 0)), + ImmutableList.of(new PlanNodeStatsAndCostSummary(60175, 541575, 0, 0, 0)), ImmutableList.of(new JsonRenderedNode( "0", "TableScan", @@ -111,7 +111,7 @@ public void testDistributedJsonPlan() ImmutableList.of("quantity := tpch:quantity"), ImmutableList.of(new PlanNodeStatsAndCostSummary(60175, 541575, 541575, 0, 0)), ImmutableList.of())))))))); - MaterializedResult expectedPlan = resultBuilder(queryRunner.getDefaultSession(), createVarcharType(2072)) + MaterializedResult expectedPlan = resultBuilder(queryRunner.getDefaultSession(), createVarcharType(2058)) .row(DISTRIBUTED_PLAN_JSON_CODEC.toJson(distributedPlan)) .build(); assertThat(actualPlan).isEqualTo(expectedPlan); @@ -127,14 +127,14 @@ public void testLogicalJsonPlan() ImmutableMap.of("columnNames", "[quantity]"), ImmutableList.of(typedSymbol("quantity", "double")), ImmutableList.of(), - ImmutableList.of(new PlanNodeStatsAndCostSummary(10, 90, 541665, 0, 0)), + ImmutableList.of(new PlanNodeStatsAndCostSummary(10, 90, 0, 0, 0)), ImmutableList.of(new JsonRenderedNode( "98", "Limit", ImmutableMap.of("count", "10", "withTies", "", "inputPreSortedBy", "[]"), ImmutableList.of(typedSymbol("quantity", "double")), ImmutableList.of(), - ImmutableList.of(new PlanNodeStatsAndCostSummary(10, 90, 541665, 0, 0)), + ImmutableList.of(new PlanNodeStatsAndCostSummary(10, 90, 90, 0, 0)), ImmutableList.of(new JsonRenderedNode( "147", "LocalExchange", @@ -145,7 +145,7 @@ public void testLogicalJsonPlan() "arguments", "[]"), ImmutableList.of(typedSymbol("quantity", "double")), ImmutableList.of(), - ImmutableList.of(new PlanNodeStatsAndCostSummary(60175, 541575, 541575, 0, 0)), + ImmutableList.of(new PlanNodeStatsAndCostSummary(60175, 541575, 0, 0, 0)), ImmutableList.of(new JsonRenderedNode( "0", "TableScan", @@ -154,7 +154,7 @@ public void testLogicalJsonPlan() ImmutableList.of("quantity := tpch:quantity"), ImmutableList.of(new PlanNodeStatsAndCostSummary(60175, 541575, 541575, 0, 0)), ImmutableList.of()))))))); - MaterializedResult expectedPlan = resultBuilder(queryRunner.getDefaultSession(), createVarcharType(1898)) + MaterializedResult expectedPlan = resultBuilder(queryRunner.getDefaultSession(), createVarcharType(1884)) .row(JSON_RENDERED_NODE_CODEC.toJson(expectedJsonNode)) .build(); assertThat(actualPlan).isEqualTo(expectedPlan); diff --git a/testing/trino-tests/src/test/java/io/trino/tests/TestLocalQueries.java b/testing/trino-tests/src/test/java/io/trino/tests/TestLocalQueries.java index 1370c4f8d099..48f2ffe99f24 100644 --- a/testing/trino-tests/src/test/java/io/trino/tests/TestLocalQueries.java +++ b/testing/trino-tests/src/test/java/io/trino/tests/TestLocalQueries.java @@ -48,6 +48,7 @@ public static LocalQueryRunner createLocalQueryRunner() .build(); LocalQueryRunner localQueryRunner = LocalQueryRunner.builder(defaultSession) + .withNodeCountForStats(1) .build(); // add the tpch catalog From 59a645d62ed18a78874472cb8895b66279de8b79 Mon Sep 17 00:00:00 2001 From: Karol Sobczak Date: Fri, 23 Sep 2022 12:25:27 +0200 Subject: [PATCH 2/2] Do not print Estimates line when estimates are absent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously: └─ Aggregate[type = PARTIAL, keys = [field], hash = [$hashvalue_3]] │ Layout: [field:integer, $hashvalue_3:bigint, count_2:bigint] │ Estimates: │ count_2 := count("field_0") (mask = expr) Now: └─ Aggregate[type = PARTIAL, keys = [field], hash = [$hashvalue_3]] │ Layout: [field:integer, $hashvalue_3:bigint, count_2:bigint] │ count_2 := count("field_0") (mask = expr) --- .../io/trino/sql/planner/planprinter/TextRenderer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/TextRenderer.java b/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/TextRenderer.java index 5d1dac1a2248..898386e3c4d6 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/TextRenderer.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/TextRenderer.java @@ -83,9 +83,9 @@ private String writeTextOutput(StringBuilder output, PlanRepresentation plan, In output.append(indentMultilineString(reorderJoinStatsAndCost, indent.detailIndent())); } - String estimates = printEstimates(plan, node); + List estimates = node.getEstimates(plan.getTypes()); if (!estimates.isEmpty()) { - output.append(indentMultilineString(estimates, indent.detailIndent())); + output.append(indentMultilineString(printEstimates(estimates), indent.detailIndent())); } String stats = printStats(plan, node); @@ -265,9 +265,9 @@ private String printReorderJoinStatsAndCost(NodeRepresentation node) return ""; } - private String printEstimates(PlanRepresentation plan, NodeRepresentation node) + private String printEstimates(List estimates) { - return node.getEstimates(plan.getTypes()).stream() + return estimates.stream() .map(this::formatPlanNodeStatsAndCostSummary) .collect(joining("/", "Estimates: ", "\n")); }