Stamatis Zampetakis created IMPALA-15334:
--------------------------------------------

             Summary: Decompose unrewritable CTE suggestions to explore more 
rewrites
                 Key: IMPALA-15334
                 URL: https://issues.apache.org/jira/browse/IMPALA-15334
             Project: IMPALA
          Issue Type: Sub-task
          Components: Frontend
            Reporter: Stamatis Zampetakis
            Assignee: Stamatis Zampetakis


The [CTE 
suggester|https://github.com/apache/impala/blob/7a3cb82b49d845bc5ef597e598f589593dd13549/java/calcite-planner/src/main/java/org/apache/impala/calcite/service/CalciteOptimizer.java#L384]
 traverses a plan and identifies commonalities and sub-trees appearing multiple 
times in the query. There are no structural restrictions on the output 
suggestions thus they may contain any kind of relational expression (RelNode). 

However the [rewrite 
algorithm|https://github.com/apache/impala/blob/7a3cb82b49d845bc5ef597e598f589593dd13549/java/calcite-planner/src/main/java/org/apache/impala/calcite/service/CalciteOptimizer.java#L406]
 imposes limitations on the structure of views/CTEs to be rewritable:
 # Only Scan, Filter, Join (inner), and Project nodes, in any order
 # Aggregate node followed by Scan, Filter, Join (inner), and Project nodes, in 
any order

In various cases, notably TPC-DS queries the default suggester implementation 
returns unrewritable CTEs. For example, for Q64 the suggester returns:
++

+cte_suggestion_2+
{noformat}
LogicalJoin(condition=[=($0, $14)], joinType=[inner])
  LogicalJoin(condition=[=($0, $12)], joinType=[inner])
    LogicalFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($7), IS NOT 
NULL($11), IS NOT NULL($5), IS NOT NULL($1), IS NOT NULL($2), IS NOT NULL($6), 
IS NOT NULL($3), IS NOT NULL($4))])
      LogicalProject(ss_item_sk=[$1], ss_customer_sk=[$2], ss_cdemo_sk=[$3], 
ss_hdemo_sk=[$4], ss_addr_sk=[$5], ss_store_sk=[$6], ss_promo_sk=[$7], 
ss_ticket_number=[$8], ss_wholesale_cost=[$10], ss_list_price=[$11], 
ss_coupon_amt=[$18], ss_sold_date_sk=[$22])
        LogicalTableScan(table=[[tpcds_partitioned_parquet_snap, store_sales]])
    LogicalProject(i_item_sk=[$0], i_product_name=[$3])
      LogicalFilter(condition=[AND(SEARCH($2, 
Sarg[_UTF-8'burlywood':VARCHAR(2147483647) CHARACTER SET "UTF-8", 
_UTF-8'floral':VARCHAR(2147483647) CHARACTER SET "UTF-8", 
_UTF-8'indian':VARCHAR(2147483647) CHARACTER SET "UTF-8", 
_UTF-8'medium':VARCHAR(2147483647) CHARACTER SET "UTF-8", 
_UTF-8'purple':VARCHAR(2147483647) CHARACTER SET "UTF-8", 
_UTF-8'spring':VARCHAR(2147483647) CHARACTER SET "UTF-8"]:VARCHAR(2147483647) 
CHARACTER SET "UTF-8"), SEARCH($1, Sarg[[65.00:DECIMAL(7, 2)..74.00:DECIMAL(7, 
2)]]:DECIMAL(7, 2)), IS NOT NULL($0))])
        LogicalProject(i_item_sk=[$0], i_current_price=[$5], i_color=[$17], 
i_product_name=[$21])
          LogicalTableScan(table=[[tpcds_partitioned_parquet_snap, item]])
  LogicalFilter(condition=[>($1, *(2:DECIMAL(3, 0), $2))])
    LogicalAggregate(group=[{0}], SALE=[SUM($1)], REFUND=[SUM($2)])
      LogicalProject(CS_ITEM_SK=[$0], cs_ext_list_price=[$2], $f2=[+(+($5, $6), 
$7)])
        LogicalJoin(condition=[AND(=($0, $3), =($1, $4))], joinType=[inner])
          LogicalFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($1))])
            LogicalProject(cs_item_sk=[$14], cs_order_number=[$16], 
cs_ext_list_price=[$24])
              LogicalTableScan(table=[[tpcds_partitioned_parquet_snap, 
catalog_sales]])
          LogicalFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($1))])
            LogicalProject(cr_item_sk=[$1], cr_order_number=[$15], 
cr_refunded_cash=[$22], cr_reversed_charge=[$23], cr_store_credit=[$24])
              LogicalTableScan(table=[[tpcds_partitioned_parquet_snap, 
catalog_returns]]){noformat}
The suggestion is not rewritable cause it contains a {*}nested aggregate{*}. As 
per limitation 2, only *one* top-level aggregate is allowed.

We cannot use the cte_suggestion_2 as it is but if we decompose it into 
rewritable components we can still exploit some sharing possibilities. The 
suggestion for Q64 can be split into two rewritable parts.

+PartA+
{noformat}
LogicalJoin(condition=[=($0, $12)], joinType=[inner])
    LogicalFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($7), IS NOT 
NULL($11), IS NOT NULL($5), IS NOT NULL($1), IS NOT NULL($2), IS NOT NULL($6), 
IS NOT NULL($3), IS NOT NULL($4))])
      LogicalProject(ss_item_sk=[$1], ss_customer_sk=[$2], ss_cdemo_sk=[$3], 
ss_hdemo_sk=[$4], ss_addr_sk=[$5], ss_store_sk=[$6], ss_promo_sk=[$7], 
ss_ticket_number=[$8], ss_wholesale_cost=[$10], ss_list_price=[$11], 
ss_coupon_amt=[$18], ss_sold_date_sk=[$22])
        LogicalTableScan(table=[[tpcds_partitioned_parquet_snap, store_sales]])
    LogicalProject(i_item_sk=[$0], i_product_name=[$3])
      LogicalFilter(condition=[AND(SEARCH($2, 
Sarg[_UTF-8'burlywood':VARCHAR(2147483647) CHARACTER SET "UTF-8", 
_UTF-8'floral':VARCHAR(2147483647) CHARACTER SET "UTF-8", 
_UTF-8'indian':VARCHAR(2147483647) CHARACTER SET "UTF-8", 
_UTF-8'medium':VARCHAR(2147483647) CHARACTER SET "UTF-8", 
_UTF-8'purple':VARCHAR(2147483647) CHARACTER SET "UTF-8", 
_UTF-8'spring':VARCHAR(2147483647) CHARACTER SET "UTF-8"]:VARCHAR(2147483647) 
CHARACTER SET "UTF-8"), SEARCH($1, Sarg[[65.00:DECIMAL(7, 2)..74.00:DECIMAL(7, 
2)]]:DECIMAL(7, 2)), IS NOT NULL($0))])
        LogicalProject(i_item_sk=[$0], i_current_price=[$5], i_color=[$17], 
i_product_name=[$21])
          LogicalTableScan(table=[[tpcds_partitioned_parquet_snap, item]])
{noformat}
+PartB+
{noformat}
LogicalAggregate(group=[{0}], SALE=[SUM($1)], REFUND=[SUM($2)])
  LogicalProject(CS_ITEM_SK=[$0], cs_ext_list_price=[$2], $f2=[+(+($5, $6), 
$7)])
    LogicalJoin(condition=[AND(=($0, $3), =($1, $4))], joinType=[inner])
      LogicalFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($1))])
        LogicalProject(cs_item_sk=[$14], cs_order_number=[$16], 
cs_ext_list_price=[$24])
          LogicalTableScan(table=[[tpcds_partitioned_parquet_snap, 
catalog_sales]])
      LogicalFilter(condition=[AND(IS NOT NULL($0), IS NOT NULL($1))])
        LogicalProject(cr_item_sk=[$1], cr_order_number=[$15], 
cr_refunded_cash=[$22], cr_reversed_charge=[$23], cr_store_credit=[$24])
          LogicalTableScan(table=[[tpcds_partitioned_parquet_snap, 
catalog_returns]]) {noformat}
Unrewritable suggestions occur for various other TPC-DS queries such as Q14, 
Q23, Q44, Q58, Q65, and Q83.

I propose to add an additional step after the suggester to decompose 
unrewritable CTE suggestions to valid rewritable candidates to explore more 
rewrites.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to