Skip to content

Commit cce2892

Browse files
committed
opt: add cost penalties and aux flags to log line
All cost penalties and auxiliary flags are now printed in the tracing log for custom and generic query plan costs. This will aid in debugging. Release note: None
1 parent f480dff commit cce2892

File tree

3 files changed

+70
-8
lines changed

3 files changed

+70
-8
lines changed

pkg/sql/opt/memo/cost.go

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55

66
package memo
77

8-
import "math"
8+
import (
9+
"fmt"
10+
"math"
11+
"strings"
12+
)
913

1014
// Cost is the best-effort approximation of the actual cost of executing a
1115
// particular operator tree.
@@ -128,3 +132,37 @@ const (
128132
// NoPenalties represents no penalties.
129133
NoPenalties Penalties = 0
130134
)
135+
136+
// Summary returns a short string describing the cost. The format is:
137+
//
138+
// <Cost>:<Penalties>:<aux>
139+
//
140+
// Where:
141+
//
142+
// <Cost> is the floating point cost value.
143+
// <Penalties> contains "H", "F", or "U" for HugeCostPenalty, FullScanPenalty,
144+
// and UnboundedCardinalityPenalty, respectively.
145+
// <aux> contains a number for full scan count and "u" for
146+
// unboundedCardinality.
147+
//
148+
// For example, the summary "1.23:HF:5fu" indicates a cost of 1.23 with the
149+
// HugeCostPenalty and FullScanPenalty penalties, 5 full scans, and the
150+
// unboundedCardinality flag set.
151+
func (c Cost) Summary() string {
152+
var sb strings.Builder
153+
_, _ = fmt.Fprintf(&sb, "%.9g:", c.C)
154+
if c.Penalties&HugeCostPenalty != 0 {
155+
sb.WriteByte('H')
156+
}
157+
if c.Penalties&FullScanPenalty != 0 {
158+
sb.WriteByte('F')
159+
}
160+
if c.Penalties&UnboundedCardinalityPenalty != 0 {
161+
sb.WriteByte('U')
162+
}
163+
_, _ = fmt.Fprintf(&sb, ":%df", c.aux.fullScanCount)
164+
if c.aux.unboundedCardinality {
165+
sb.WriteByte('u')
166+
}
167+
return sb.String()
168+
}

pkg/sql/opt/memo/cost_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,28 @@ func TestCostAdd(t *testing.T) {
7070
}
7171
}
7272
}
73+
74+
func TestCostSummary(t *testing.T) {
75+
testCases := []struct {
76+
c Cost
77+
expected string
78+
}{
79+
{Cost{C: 1.0}, "1::0f"},
80+
{Cost{C: 1.23}, "1.23::0f"},
81+
{Cost{C: 1.23456}, "1.23456::0f"},
82+
{Cost{C: 1.23, Penalties: HugeCostPenalty}, "1.23:H:0f"},
83+
{Cost{C: 1.23, Penalties: FullScanPenalty}, "1.23:F:0f"},
84+
{Cost{C: 1.23, Penalties: UnboundedCardinalityPenalty}, "1.23:U:0f"},
85+
{Cost{C: 1.23, Penalties: HugeCostPenalty | FullScanPenalty | UnboundedCardinalityPenalty}, "1.23:HFU:0f"},
86+
{Cost{C: 1.23, Penalties: HugeCostPenalty | FullScanPenalty | UnboundedCardinalityPenalty}, "1.23:HFU:0f"},
87+
{Cost{C: 1.23, aux: testAux{5, false}}, "1.23::5f"},
88+
{Cost{C: 1.23, aux: testAux{0, true}}, "1.23::0fu"},
89+
{Cost{C: 1.23, aux: testAux{5, true}}, "1.23::5fu"},
90+
{Cost{C: 1.23, Penalties: HugeCostPenalty | FullScanPenalty, aux: testAux{5, true}}, "1.23:HF:5fu"},
91+
}
92+
for _, tc := range testCases {
93+
if r := tc.c.Summary(); r != tc.expected {
94+
t.Errorf("expected %q, got %q", tc.expected, r)
95+
}
96+
}
97+
}

pkg/sql/prep/statement.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -222,15 +222,14 @@ func (p *planCosts) avgCustom() memo.Cost {
222222
// Summary returns a single-line string summarizing the custom and generic plan
223223
// costs and full scan counts. The format for custom costs is:
224224
//
225-
// average_custom_cost [num_custom_costs]{custom_cost_0:full_scan_count ...}
225+
// average_custom_cost_float [<count>]{custom_summary_0 custom_summary_1 ...}
226226
//
227-
// The format for generic costs is:
228-
//
229-
// generic_cost:generic_full_scan_count
227+
// The custom costs are follow by the generic cost summary. See
228+
// (memo.Cost).Summary for details.
230229
//
231230
// A full example:
232231
//
233-
// custom costs: 1.23 [3]{1.23:0 1.23:0 1.23:0}, generic cost: 4.56:1
232+
// custom costs: 1.5 [3]{1.25:U:0u 1.75:U:0u 1.50:U:0u}, generic cost: 4.56:U:0u
234233
func (p *planCosts) Summary() string {
235234
var sb strings.Builder
236235
sb.WriteString("custom costs: ")
@@ -240,15 +239,15 @@ func (p *planCosts) Summary() string {
240239
if i > 0 {
241240
sb.WriteByte(' ')
242241
}
243-
sb.WriteString(fmt.Sprintf("%.9g:%d", p.custom.costs[i].C, p.custom.costs[i].FullScanCount()))
242+
sb.WriteString(p.custom.costs[i].Summary())
244243
}
245244
sb.WriteByte('}')
246245
} else {
247246
sb.WriteString("none")
248247
}
249248
sb.WriteString(", generic cost: ")
250249
if p.HasGeneric() {
251-
sb.WriteString(fmt.Sprintf("%.9g:%d", p.generic.C, p.generic.FullScanCount()))
250+
sb.WriteString(p.generic.Summary())
252251
} else {
253252
sb.WriteString("none")
254253
}

0 commit comments

Comments
 (0)