当前位置: 首页 > article >正文

Apache Calcite - 查询优化之逻辑优化简介

查询优化简介

Apache Calcite 对 SQL 进行优化是指通过一系列的规则和策略,将原始的 SQL 查询转换为更高效的执行计划,从而提高查询性能。优化过程通常包括逻辑优化和物理优化两个阶段。

逻辑优化

逻辑优化主要集中在对查询的逻辑执行计划进行改进,而不涉及具体的物理执行细节。逻辑优化的目标是简化查询、减少不必要的计算、优化数据访问路径等。

常见的逻辑优化

下面介绍常见的逻辑优化,最终对比原始和结果逻辑计划进行差异比较。得到优化后的逻辑计划最终再完成执行物理数据查询。

谓词下推(Predicate Pushdown)

将过滤条件尽可能早地应用,以减少中间结果集的大小。

-- 原始查询
SELECT e.name, e.salary, d.name AS department_name
FROM employees e
JOIN departments d ON e.department_id = d.id
WHERE e.salary > 1000 AND d.name = 'Sales';


-- 可能得原始逻辑计划
LogicalProject(name=[$0], salary=[$1], department_name=[$3])
  LogicalFilter(condition=[AND(>($1, 1000), =($3, 'Sales'))])
    LogicalJoin(condition=[=($2, $4)], joinType=[inner])
      LogicalTableScan(table=[[employees]])
      LogicalTableScan(table=[[departments]])

在这个计划中,过滤条件 e.salary > 1000 和 d.name = ‘Sales’ 是在 LogicalJoin 之后才应用的,这意味着在连接之前没有减少数据量。

优化后的逻辑计划(谓词下推)
通过谓词下推优化,过滤条件尽早应用,以减少中间结果集的大小:

LogicalProject(name=[$0], salary=[$1], department_name=[$3])
  LogicalJoin(condition=[=($2, $4)], joinType=[inner])
    LogicalFilter(condition=[>($1, 1000)])
      LogicalTableScan(table=[[employees]])
    LogicalFilter(condition=[=($3, 'Sales')])
      LogicalTableScan(table=[[departments]])

在这个优化后的计划中,过滤条件 e.salary > 1000 被推到 employees 表的扫描之前,过滤条件 d.name = ‘Sales’ 被推到 departments 表的扫描之前。这样可以在连接之前减少数据量,提高查询性能。

投影下推(Projection Pushdown)

只保留查询中实际需要的列,避免不必要的列传输和计算。

假设我们有一个表 employees,包含以下列:id, name, department_id, salary, address。我们需要查询 department_id 为 10 的员工的 name 和 salary。

原始查询

SELECT name, salary
FROM employees
WHERE department_id = 10;

原始逻辑计划

LogicalProject(name=[$1], salary=[$3])
  LogicalFilter(condition=[=($2, 10)])
    LogicalTableScan(table=[[employees]])

在这个计划中,LogicalTableScan 扫描了整个 employees 表的所有列,然后在 LogicalFilter 中应用过滤条件,最后在 LogicalProject 中选择所需的列。这意味着在扫描表时,所有列都被读取,即使只需要 name 和 salary 列。

优化后的逻辑计划(投影下推)
通过投影下推优化,尽早选择所需的列,以减少不必要的数据传输:

LogicalProject(name=[$1], salary=[$3])
  LogicalFilter(condition=[=($2, 10)])
    LogicalTableScan(table=[[employees]], projects=[name, salary, department_id])

在这个优化后的计划中,LogicalTableScan 只扫描 name, salary 和 department_id 列,而不是整个表的所有列。这样可以减少数据传输量,提高查询性能。

总结

Calcite的逻辑查询优化的一个重要目标是通过减少关系表达式树的深度、操作数量、连接顺序。来优化查询。最终这种优化可以为后续优化提高效率。

减少关系表达式树的深度

  • 谓词下推:将过滤条件尽早应用,以减少中间结果集的大小。例如,将 WHERE 子句中的条件下推到扫描操作之前。
  • 投影下推:将选择的列尽早应用,以减少中间结果集的宽度。例如,将 SELECT 子句中的列选择下推到扫描操作之前。

减少操作数量

  • 子查询合并:将子查询合并到主查询中,以减少嵌套查询的数量。
  • 合并相邻操作:合并相邻的同类操作,例如相邻的投影操作,以减少不必要的操作。
    优化连接顺序:

重新排列连接顺序

  • 通过重新排列连接操作的顺序,减少连接操作的成本。例如,将小表放在连接操作的内侧。

http://www.kler.cn/news/363653.html

相关文章:

  • 基于django的个人相册日记管理系统
  • 高薪、高含金量、高性价比的“三高”证书——PMP证书
  • 麒麟V10、UOS系统实现在线合并多个Word文件
  • 力扣第246题“中心对称数”
  • 在linux上安装r-base和rpy2到conda环境
  • JMeter使用不同方式传递接口参数
  • 12.useComponentWillUnmount
  • 【MySQL】提高篇—复杂查询:子查询与嵌套查询
  • 【C++笔记】类和对象(下)
  • 02.05、链表求和
  • 【状态机DP】力扣2786. 访问数组中的位置使分数最大
  • 【大模型】3分钟了解提示(Prompt)工程、检索增强(RAG)和微调
  • 前端埋点(tracking)实现多种方式
  • Electron-(三)网页报错处理与请求监听
  • html小游戏-飞机大战
  • 1024感悟 → 勋章
  • Java项目-基于springboot框架的原创歌曲分享系统项目实战(附源码+文档)
  • 人工智能+医学
  • 【C++篇】C++类与对象深度解析(五):友元机制、内部类与匿名对象的讲解
  • 预训练模型通过 prompt(提示)生成的“软标签”是什么
  • C#从零开始学习(封装(5)
  • JAVA Maven 的安装与配置
  • redis 使用
  • 04. VSCODE:C/C++简捷项目专用配置
  • MMA: Multi-Modal Adapter for Vision-Language Models
  • 第1节 什么是鸿蒙系统