• 基于calcite做傻瓜式的sql优化(一)


    我们要做的事情大概分3步:

    1、需求的描述(主要把问题点抛出来)

    2、解决如何优化sql性能的问题(hive关于一条sql的生命周期源码的分析),也就是如何对你的sql进行RBO和CBO的优化

    3、解决如何自动识别sql元数据的问题(antlr关于如何深度优先遍历语法树)

    背景:

    我们有一套智能中台系统,可以基于配置化的方式就可以做出各种图表。说白了就是可以快速给业务通过图表的方式展现数据

    需求:

    通过配置来快速展现数据固然是好的事情,但稍微思考一下其实也是通过配置的方式来生成sql;
    那么生成的这个sql性能不见得会很好吧?(其实会非常的不好)  

    比如,我们通过配置的方式生成的sql大概这个样子:

    select 
      t0.tree_id, 
      sum(t0.gap) as num 
    from 
      (
        SELECT 
          w.tree_id, 
          w.gap, 
          r.executed_sql 
        FROM 
          data_middleground.view_mkt_node_kpi_warning w 
          JOIN data_middleground.view_mkt_node_result r ON w.tree_id = r.tree_id 
        WHERE 
          w.warning_status = 0 
          and r.is_del = 0
      ) t0 
    where 
      t0.gap > 1 
    group by 
      t0.tree_id 
    order by 
      tree_id desc

    花一分钟仔细看下这个sql,会发现其实很烂,性能点在:

    1、表关联的时候,谓词没有下推
    2、多个谓词分别出现在关联和聚合的地方,没有做过滤合并和下推
    3、有聚合操作,是否可以聚合下推?

    烂sql的执行计划:

    LogicalSort(sort0=[$0], dir0=[DESC])
      LogicalAggregate(group=[{0}], num=[SUM($1)])
        LogicalProject(tree_id=[$0], gap=[$1])
          LogicalFilter(condition=[>($1, 1)])
            LogicalProject(tree_id=[$0], gap=[$1], executed_sql=[$4])
              LogicalFilter(condition=[AND(=($2, 0), =($5, 0))])
                LogicalJoin(condition=[=($0, $3)], joinType=[inner])
                  EnumerableTableScan(table=[[data_middleground, view_mkt_node_kpi_warning]])
                  EnumerableTableScan(table=[[data_middleground, view_mkt_node_result]])

    那么能否通过一套代码处理后,让“烂sql1”进入代码,出来后是“好sql2”

    先看下成果,优化后的sql:

    SELECT 
      `t0`.`tree_id`, 
      SUM(`t0`.`gap`) AS `num` 
    FROM 
      (
        SELECT 
          * 
        FROM 
          `data_middleground`.`view_mkt_node_result` 
        WHERE 
          `is_del` = 0
      ) AS `t` 
      INNER JOIN (
        SELECT 
          * 
        FROM 
          `data_middleground`.`view_mkt_node_kpi_warning` 
        WHERE 
          `warning_status` = 0 
          AND `gap` > 1
      ) AS `t0` ON `t`.`tree_id` = `t0`.`tree_id` 
    GROUP BY 
      `t0`.`tree_id` 
    ORDER BY 
      `t0`.`tree_id` IS NULL DESC, 
      `t0`.`tree_id` DESC

    请花一分钟看下sql,会发现这真TM是个好的sql;

    执行计划:

    LogicalSort(sort0=[$0], dir0=[DESC])
      LogicalAggregate(group=[{0}], num=[SUM($1)])
        LogicalProject(tree_id=[$0], gap=[$1])
          LogicalProject(tree_id=[$0], gap=[$1], executed_sql=[$4])
            LogicalJoin(condition=[=($0, $3)], joinType=[inner])
              LogicalFilter(condition=[AND(=($2, 0), >($1, 1))])
                EnumerableTableScan(table=[[data_middleground, view_mkt_node_kpi_warning]])
              LogicalFilter(condition=[=($2, 0)])
                EnumerableTableScan(table=[[data_middleground, view_mkt_node_result]])

    那么如何实现上面的功能呢?可以参考spark、hive、druid等,他们是如何做的sql优化。这里我参考的是hive;

    那么接下来通过走读hive源码的方式来看下,hive是如何处理一条sql的【请看下一篇:基于calcite做傻瓜式的sql优化(二)

      

  • 相关阅读:
    MySQL学习笔记
    为什么使用多态?实现多态的有哪些方式
    C++中派生类使用基类成员的问题
    实现Modbus ASCII多主站应用
    PHP第四天 函数引用传值
    Webpack 快速上手(下)
    Java---23种设计模式(九)------组合模式
    【笔记】Linux就该这么学-第六课第四章
    Node.js HTTPS
    Node.js Smalloc
  • 原文地址:https://www.cnblogs.com/niutao/p/13982876.html
Copyright © 2020-2023  润新知