|
26 | 26 | #include "optimizer/paths.h"
|
27 | 27 | #include "partitioning/partbounds.h"
|
28 | 28 | #include "utils/lsyscache.h"
|
| 29 | +#include "utils/selfuncs.h" |
29 | 30 |
|
30 | 31 | /* Consider reordering of GROUP BY keys? */
|
31 | 32 | bool enable_group_by_reordering = true;
|
@@ -472,6 +473,10 @@ get_useful_group_keys_orderings(PlannerInfo *root, Path *path)
|
472 | 473 | List *pathkeys = root->group_pathkeys;
|
473 | 474 | List *clauses = root->processed_groupClause;
|
474 | 475 |
|
| 476 | + double nd_max = 0.0; |
| 477 | + PathKey *pk_opt; |
| 478 | + ListCell *lc1, *lc2; |
| 479 | + |
475 | 480 | /* always return at least the original pathkeys/clauses */
|
476 | 481 | info = makeNode(GroupByOrdering);
|
477 | 482 | info->pathkeys = pathkeys;
|
@@ -517,6 +522,71 @@ get_useful_group_keys_orderings(PlannerInfo *root, Path *path)
|
517 | 522 | }
|
518 | 523 | }
|
519 | 524 |
|
| 525 | + |
| 526 | + /* |
| 527 | + * Let's try the order with the column having max ndistinct value |
| 528 | + */ |
| 529 | + |
| 530 | + forboth(lc1, root->group_pathkeys, lc2, root->processed_groupClause) |
| 531 | + { |
| 532 | + PathKey *pkey = lfirst_node(PathKey, lc1); |
| 533 | + SortGroupClause *gc = (SortGroupClause *) lfirst(lc2); |
| 534 | + Node *node; |
| 535 | + Bitmapset *relids; |
| 536 | + VariableStatData vardata; |
| 537 | + double nd = -1; |
| 538 | + bool isdefault; |
| 539 | + |
| 540 | + if (foreach_current_index(lc1) >= root->num_groupby_pathkeys) |
| 541 | + break; |
| 542 | + |
| 543 | + node = get_sortgroupclause_expr(gc, root->parse->targetList); |
| 544 | + relids = pull_varnos(root, node); |
| 545 | + |
| 546 | + if (bms_num_members(relids) != 1 && bms_is_member(0, relids)) |
| 547 | + /* |
| 548 | + *Although functional index can estimate distincts here, the chance |
| 549 | + * is too low. |
| 550 | + */ |
| 551 | + continue; |
| 552 | + |
| 553 | + examine_variable(root, node, 0, &vardata); |
| 554 | + if (!HeapTupleIsValid(vardata.statsTuple)) |
| 555 | + continue; |
| 556 | + nd = get_variable_numdistinct(&vardata, &isdefault); |
| 557 | + ReleaseVariableStats(vardata); |
| 558 | + if (isdefault) |
| 559 | + continue; |
| 560 | + |
| 561 | + Assert(nd >= 0); |
| 562 | + if (nd > nd_max) |
| 563 | + { |
| 564 | + nd_max = nd; |
| 565 | + pk_opt = pkey; |
| 566 | + } |
| 567 | + } |
| 568 | + |
| 569 | + if (pk_opt != NULL) |
| 570 | + { |
| 571 | + List *new_pathkeys = list_make1(pk_opt); |
| 572 | + int n; |
| 573 | + |
| 574 | + new_pathkeys = list_concat_unique_ptr(new_pathkeys, root->group_pathkeys); |
| 575 | + n = group_keys_reorder_by_pathkeys(new_pathkeys, &pathkeys, &clauses, |
| 576 | + root->num_groupby_pathkeys); |
| 577 | + |
| 578 | + if (n > 0 && |
| 579 | + (enable_incremental_sort || n == root->num_groupby_pathkeys) && |
| 580 | + compare_pathkeys(pathkeys, root->group_pathkeys) != PATHKEYS_EQUAL) |
| 581 | + { |
| 582 | + info = makeNode(GroupByOrdering); |
| 583 | + info->pathkeys = pathkeys; |
| 584 | + info->clauses = clauses; |
| 585 | + |
| 586 | + infos = lappend(infos, info); |
| 587 | + } |
| 588 | + } |
| 589 | + |
520 | 590 | #ifdef USE_ASSERT_CHECKING
|
521 | 591 | {
|
522 | 592 | GroupByOrdering *pinfo = linitial_node(GroupByOrdering, infos);
|
|
0 commit comments