@@ -214,6 +214,8 @@ static bool get_actual_variable_endpoint(Relation heapRel,
214
214
MemoryContext outercontext ,
215
215
Datum * endpointDatum );
216
216
static RelOptInfo * find_join_input_rel (PlannerInfo * root , Relids relids );
217
+ static EquivalenceMember * identify_sort_ecmember (PlannerInfo * root ,
218
+ EquivalenceClass * ec );
217
219
218
220
219
221
/*
@@ -3468,12 +3470,34 @@ estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows,
3468
3470
i = 0 ;
3469
3471
foreach (l , groupExprs )
3470
3472
{
3471
- Node * groupexpr = (Node * ) lfirst (l );
3473
+ Node * node = (Node * ) lfirst (l );
3474
+ Node * groupexpr ;
3472
3475
double this_srf_multiplier ;
3473
3476
VariableStatData vardata ;
3474
3477
List * varshere ;
3475
3478
ListCell * l2 ;
3476
3479
3480
+ /* Find an expression beforehand */
3481
+ if (IsA (node , PathKey ))
3482
+ {
3483
+ PathKey * key = (PathKey * ) node ;
3484
+ EquivalenceMember * em = identify_sort_ecmember (root , key -> pk_eclass );
3485
+
3486
+ /*
3487
+ * Check if the expression contains Var with "varno 0" so that we
3488
+ * don't call estimate_num_groups in that case.
3489
+ */
3490
+ if (bms_is_member (0 , pull_varnos (root , (Node * ) em -> em_expr )))
3491
+ {
3492
+ /* Return 'unknown' value */
3493
+ return 0.0 ;
3494
+ }
3495
+
3496
+ groupexpr = (Node * ) em -> em_expr ;
3497
+ }
3498
+ else
3499
+ groupexpr = node ;
3500
+
3477
3501
/* is expression in this grouping set? */
3478
3502
if (pgset && !list_member_int (* pgset , i ++ ))
3479
3503
continue ;
@@ -8404,3 +8428,64 @@ brincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
8404
8428
8405
8429
* indexPages = index -> pages ;
8406
8430
}
8431
+
8432
+ /*
8433
+ * Find suitable member of the equivalence class.
8434
+ * Passing through the list of EC members find the member with minimum of
8435
+ * distinct values. Cache estimated number of distincts in the em_ndistinct
8436
+ * field of each member.
8437
+ */
8438
+ static EquivalenceMember *
8439
+ identify_sort_ecmember (PlannerInfo * root , EquivalenceClass * ec )
8440
+ {
8441
+ EquivalenceMember * candidate = linitial (ec -> ec_members );
8442
+
8443
+ if (root == NULL )
8444
+ /* Fast path */
8445
+ return candidate ;
8446
+
8447
+ foreach_node (EquivalenceMember , em , ec -> ec_members )
8448
+ {
8449
+ VariableStatData vardata ;
8450
+
8451
+ if (em -> em_ndistinct == 0. )
8452
+ /* Nothing helpful */
8453
+ continue ;
8454
+
8455
+ if (em -> em_is_child || em -> em_is_const || bms_is_empty (em -> em_relids ) ||
8456
+ bms_is_member (0 , em -> em_relids ))
8457
+ {
8458
+ em -> em_ndistinct = 0. ;
8459
+ continue ;
8460
+ }
8461
+
8462
+ if (em -> em_ndistinct < 0. )
8463
+ {
8464
+ bool isdefault = true;
8465
+ double ndist = 0. ;
8466
+
8467
+ /* Let's check candidate's ndistinct value */
8468
+ examine_variable (root , (Node * ) em -> em_expr , 0 , & vardata );
8469
+ if (HeapTupleIsValid (vardata .statsTuple ))
8470
+ ndist = get_variable_numdistinct (& vardata , & isdefault );
8471
+ ReleaseVariableStats (vardata );
8472
+
8473
+ if (isdefault )
8474
+ {
8475
+ em -> em_ndistinct = 0. ;
8476
+ continue ;
8477
+ }
8478
+
8479
+ em -> em_ndistinct = ndist ;
8480
+ }
8481
+
8482
+ Assert (em -> em_ndistinct > 0. );
8483
+
8484
+ if (candidate -> em_ndistinct == 0. ||
8485
+ em -> em_ndistinct < candidate -> em_ndistinct )
8486
+ candidate = em ;
8487
+ }
8488
+
8489
+ Assert (candidate != NULL );
8490
+ return candidate ;
8491
+ }
0 commit comments