@@ -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+
329346func (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