|
20 | 20 | #include "func_cache.h" |
21 | 21 | #include "hypertable.h" |
22 | 22 | #include "import/allpaths.h" |
| 23 | +#include "planner/planner.h" |
23 | 24 | #include "sort_transform.h" |
24 | 25 |
|
25 | 26 | /* This optimizations allows GROUP BY clauses that transform time in |
@@ -439,9 +440,8 @@ sort_transform_ec(PlannerInfo *root, EquivalenceClass *orig, Relids child_relids |
439 | 440 | * For example: an ORDER BY date_trunc('minute', time) can be implemented by |
440 | 441 | * an ordering of time. |
441 | 442 | */ |
442 | | -List * |
443 | | -ts_sort_transform_get_pathkeys(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, |
444 | | - Hypertable *ht) |
| 443 | +static List * |
| 444 | +sort_transform_compute_pathkeys(PlannerInfo *root, RelOptInfo *rel) |
445 | 445 | { |
446 | 446 | /* |
447 | 447 | * We attack this problem in three steps: |
@@ -552,6 +552,50 @@ ts_sort_transform_get_pathkeys(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry |
552 | 552 | return transformed_query_pathkeys; |
553 | 553 | } |
554 | 554 |
|
| 555 | +/* |
| 556 | + * The transformed pathkeys are a function of the query's ORDER BY and the |
| 557 | + * hypertable, not of the individual chunk (they reference query-global |
| 558 | + * equivalence classes; the per-chunk expressions live in the eclass's child |
| 559 | + * members). Computing them re-walks the whole ORDER BY eclass, whose membership |
| 560 | + * grows with the chunk count, so doing it once per chunk is O(chunks^2). Cache |
| 561 | + * the result on the parent hypertable rel and reuse it for every chunk. |
| 562 | + */ |
| 563 | +List * |
| 564 | +ts_sort_transform_get_pathkeys(PlannerInfo *root, RelOptInfo *rel) |
| 565 | +{ |
| 566 | + RelOptInfo *parent = NULL; |
| 567 | + |
| 568 | + if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL) |
| 569 | + { |
| 570 | + AppendRelInfo *appinfo = root->append_rel_array[rel->relid]; |
| 571 | + RelOptInfo *candidate = root->simple_rel_array[appinfo->parent_relid]; |
| 572 | + |
| 573 | + /* |
| 574 | + * A standalone chunk pulled up from a subquery (UNION ALL or a |
| 575 | + * flattened LATERAL subquery) is also an OTHER_MEMBER_REL, but its |
| 576 | + * append parent is not a hypertable. |
| 577 | + */ |
| 578 | + if (candidate->fdw_private) |
| 579 | + { |
| 580 | + parent = candidate; |
| 581 | + } |
| 582 | + } |
| 583 | + |
| 584 | + /* Standalone chunk (no parent to cache on). */ |
| 585 | + if (!parent) |
| 586 | + { |
| 587 | + return sort_transform_compute_pathkeys(root, rel); |
| 588 | + } |
| 589 | + |
| 590 | + TimescaleDBPrivate *pp = ts_get_private_reloptinfo(parent); |
| 591 | + if (!pp->transformed_sort_pathkeys_valid) |
| 592 | + { |
| 593 | + pp->transformed_sort_pathkeys = sort_transform_compute_pathkeys(root, rel); |
| 594 | + pp->transformed_sort_pathkeys_valid = true; |
| 595 | + } |
| 596 | + return pp->transformed_sort_pathkeys; |
| 597 | +} |
| 598 | + |
555 | 599 | /* |
556 | 600 | * After we have created new paths with transformed pathkeys, replace them back |
557 | 601 | * with the original pathkeys. |
|
0 commit comments