Skip to content

Commit 5e5d6af

Browse files
committed
refactor statsForRel per Nick's comments
1 parent e9af3e2 commit 5e5d6af

File tree

1 file changed

+22
-21
lines changed

1 file changed

+22
-21
lines changed

sql/memo/rel_props.go

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -326,41 +326,42 @@ func (m *Memo) CardMemoGroups(ctx *sql.Context, g *ExprGroup) {
326326
g.RelProps.SetStats(s)
327327
}
328328

329+
func estimatedCardinalityStats(jp *JoinBase) sql.Statistic {
330+
left := jp.Left.RelProps.GetStats()
331+
right := jp.Right.RelProps.GetStats()
332+
333+
distinct := math.Max(float64(left.DistinctCount()), float64(right.DistinctCount()))
334+
if distinct == 0 {
335+
m := math.Max(float64(left.RowCount()), float64(right.RowCount()))
336+
distinct = m * .80
337+
}
338+
339+
// Assume that the smaller set is surjective onto the larger set, and at least one of the sets is uniformly distributed.
340+
// If so, then the odds that a random element of each set matches can be computed as:
341+
selectivity := 1.0 / float64(distinct)
342+
card := uint64(float64(left.RowCount()*right.RowCount()) * selectivity)
343+
return &stats.Statistic{RowCnt: card}
344+
}
345+
329346
func (m *Memo) statsForRel(ctx *sql.Context, rel RelExpr) sql.Statistic {
330347
m.Tracer.PushDebugContext("statsForRel")
331348
defer m.Tracer.PopDebugContext()
332349

333350
var stat sql.Statistic
334351
switch rel := rel.(type) {
335352
case JoinRel:
336-
// different joins use different ways to estimate cardinality of outputs
337-
jp := rel.JoinPrivate()
338-
left := jp.Left.RelProps.GetStats()
339-
right := jp.Right.RelProps.GetStats()
340-
341-
distinct := math.Max(float64(left.DistinctCount()), float64(right.DistinctCount()))
342-
if distinct == 0 {
343-
m := math.Max(float64(left.RowCount()), float64(right.RowCount()))
344-
distinct = m * .80
345-
}
346-
347-
// Assume that the smaller set is surjective onto the larger set, and at least one of the sets is uniformly distributed.
348-
// If so, then the odds that a random element of each set matches can be computed as:
349-
selectivity := 1.0 / float64(distinct)
350-
card := uint64(float64(left.RowCount()*right.RowCount()) * selectivity)
351-
353+
estimatedCardStats := estimatedCardinalityStats(rel.JoinPrivate())
354+
smallestLeft := estimatedCardStats
352355
var injective bool
353-
var smallestLeft sql.Statistic
354356
var mergeStats sql.Statistic
355357
var n RelExpr = rel
356358
var done bool
357359
for n != nil && !done {
358360
switch n := n.(type) {
359361
case *LookupJoin:
360-
leftRows := n.Left.RelProps.GetStats().RowCount()
361-
if n.Injective && leftRows < card {
362+
if n.Injective {
362363
injective = true
363-
if smallestLeft == nil || leftRows < smallestLeft.RowCount() {
364+
if n.Left.RelProps.GetStats().RowCount() < smallestLeft.RowCount() {
364365
smallestLeft = n.Left.RelProps.GetStats()
365366
}
366367
}
@@ -409,7 +410,7 @@ func (m *Memo) statsForRel(ctx *sql.Context, rel RelExpr) sql.Statistic {
409410
return mergeStats
410411
}
411412

412-
return &stats.Statistic{RowCnt: card}
413+
return estimatedCardStats
413414
case *Max1Row:
414415
stat = &stats.Statistic{RowCnt: 1}
415416

0 commit comments

Comments
 (0)