0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

SQL改写消除相关子查询实践

OSC开源社区 来源:OSCHINA 社区 2023-12-27 09:51 次阅读

一、子查询

GaussDB (DWS) 根据子查询在 SQL 语句中的位置把子查询分成了子查询、子链接两种形式。

子查询 SubQuery:对应于查询解析树中的范围表 RangeTblEntry,更通俗一些指的是出现在 FROM 语句后面的独立的 SELECT 语句。

子链接 SubLink:对应于查询解析树中的表达式,更通俗一些指的是出现在 where/on 子句、targetlist 里面的语句。

1.1 非相关子查询

子查询的执行不依赖于外层父查询的任何属性值。这样子查询具有独立性,可独自求解,形成一个子查询计划先于外层的查询求解。示例:

select t1.c1,t1.c2
from t1
where t1.c1 in (
    select c2
    from t2
    where t2.c2 IN (2,3,4)
);

1.2 相关子查询

子查询的执行依赖于外层父查询的一些属性值(如下列示例 t2.c1 = t1.c1 条件中的 t1.c1)作为内层查询的一个 AND-ed 条件。这样的子查询不具备独立性,需要和外层查询按分组进行求解。

select t1.c1,t1.c2
from t1
where t1.c1 in (
    select c2
    from t2
    where t2.c1 = t1.c1 AND t2.c2 in (2,3,4)
);

二、调优实战

2.1 案例:

UPDATE t1
SET (c1,c2)=(
SELECT COALESCE(t2.c1, t1.c2),c2 FROM t2 WHERE t1.i1 = t2.i1  -- 相关标量子查询
);
其中子查询 SELECT COALESCE (t2.c1, t1.c2),c2 FROM t2 WHERE t1.i1 = t2.i1 依赖于外层父查询的 t1 表,因此属于相关子查询。执行计划:
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------
  id |                   operation                   |     A-time     | A-rows | E-rows | E-distinct |  Peak Memory   | E-memory | A-width | E-width | E-costs
 ----+-----------------------------------------------+----------------+--------+--------+------------+----------------+----------+---------+---------+---------
   1 | ->  Streaming (type: GATHER)                  | 8.998          |      0 |      1 |            | 24KB           |          |         |      17 | 9.83
   2 |    ->  Update on public.t1                    | [0.086, 0.096] |      2 |      2 |            | [308KB, 308KB] |          |         |      17 | 9.74
   3 |       ->  Seq Scan on public.t1               | [0.058, 0.074] |      2 |      2 |            | [32KB, 32KB]   | 1MB      |         |      17 | 3.73
   4 |          ->  Result  [3, SubPlan 1]           | [0.033, 0.034] |      2 |     10 |            | [16KB, 16KB]   | 1MB      |         |       6 | 1.36
   5 |             ->  Materialize                   | [4.167, 4.458] |     20 |     10 |            | [16KB, 16KB]   | 16MB     | [24,24] |       6 | 1.36
   6 |                ->  Streaming(type: BROADCAST) | [4.105, 4.406] |     10 |     10 |            | [48KB, 48KB]   | 2MB      |         |       6 | 1.33
   7 |                   ->  Seq Scan on public.t2   | [0.013, 0.013] |      5 |      5 |            | [32KB, 32KB]   | 1MB      |         |       6 | 1.02
   8 |          ->  Result  [3, SubPlan 2]           | [0.006, 0.021] |      2 |     10 |            | [16KB, 16KB]   | 1MB      |         |       6 | 1.36
   9 |             ->  Materialize                   | [0.055, 0.061] |     20 |     10 |            | [16KB, 16KB]   | 16MB     | [24,24] |       6 | 1.36
  10 |                ->  Streaming(type: BROADCAST) | [0.034, 0.040] |     10 |     10 |            | [48KB, 48KB]   | 2MB      |         |       6 | 1.33
  11 |                   ->  Seq Scan on public.t2   | [0.005, 0.009] |      5 |      5 |            | [32KB, 32KB]   | 1MB      |         |       6 | 1.02

2.2 子查询消除

改写策略就是解除子查询与父查询依赖关系,改写方案参考:

UPDATE t1
SET (c1,c2)=(t3.c1,t3.c2)
FROM (
SELECT t2.i1,COALESCE(t2.c1, t1.c2) c1,t2.c2 FROM t1,t2 WHERE t1.i1 = t2.i1
)t3
WHERE t1.i1 = t3.i1;
改写后,子查询独立,不再依赖父查询中元素。执行计划:
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
  id |                      operation                      |     A-time     | A-rows | E-rows | E-distinct |  Peak Memory   | E-memory | A-width | E-width | E-costs
 ----+-----------------------------------------------------+----------------+--------+--------+------------+----------------+----------+---------+---------+---------
   1 | ->  Streaming (type: GATHER)                        | 13.141         |      0 |      1 |            | 24KB           |          |         |      33 | 10.56
   2 |    ->  Update on public.t1                          | [6.242, 6.362] |      2 |      2 |            | [308KB, 308KB] |          |         |      33 | 10.47
   3 |       ->  Streaming(type: RESTORE)                  | [6.186, 6.310] |      2 |      2 |            | [48KB, 48KB]   | 2MB      |         |      33 | 4.46
   4 |          ->  Nested Loop (5,11)                     | [4.082, 4.801] |      2 |      2 |            | [32KB, 32KB]   | 1MB      |         |      33 | 4.44
   5 |             ->  Streaming(type: BROADCAST)          | [3.804, 4.541] |      4 |      4 |            | [48KB, 48KB]   | 2MB      |         |      27 | 2.36
   6 |                ->  Nested Loop (7,8)                | [2.972, 4.267] |      2 |      2 |            | [32KB, 32KB]   | 1MB      |         |      27 | 2.20
   7 |                   ->  Seq Scan on public.t1         | [0.010, 0.011] |      2 |      2 |            | [16KB, 16KB]   | 1MB      |         |      14 | 1.01
   8 |                   ->  Materialize                   | [2.724, 4.055] |      6 |      4 |            | [16KB, 16KB]   | 16MB     | [28,28] |      13 | 1.17
   9 |                      ->  Streaming(type: BROADCAST) | [2.667, 4.008] |      4 |      4 |            | [48KB, 48KB]   | 2MB      |         |      13 | 1.17
  10 |                         ->  Seq Scan on public.t1   | [0.008, 0.012] |      2 |      2 |            | [16KB, 16KB]   | 1MB      |         |      13 | 1.01
  11 |             ->  Materialize                         | [0.018, 0.022] |     12 |      5 |            | [16KB, 16KB]   | 16MB     | [32,32] |      14 | 2.03
  12 |                ->  Seq Scan on public.t2            | [0.007, 0.009] |






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SQL
    SQL
    +关注

    关注

    1

    文章

    738

    浏览量

    43462

原文标题:数仓调优实践丨 SQL改写消除相关子查询

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    在Delphi中动态地使用SQL查询语句

    在Delphi中动态地使用SQL查询语句在一般的数据库管理系统中,通常都需要应用SQL查询语句来提高程序的动态特性。下面介绍如何在Delphi中实现这种功能。在Delphi中,使用
    发表于 05-10 11:10

    SQL语言实现数据库记录的查询

    绝大部分DBMS都支持SQL语言,LabVIEW数据库工具包实现的实质也是基于SQL语言,它为不熟悉SQL语言的用户把SQL语言封装了起来,以方便他们使用。所以,我们也可以利用
    发表于 07-01 21:25

    高级子查询

    高级子查询(相关子查询)
    发表于 05-23 16:15

    SQL查询慢的原因分析总结

    sql 查询慢的48个原因分析 1、没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)。 2、I/O吞吐量小,形成了瓶颈效应。 3、没有创建计算列导致查询不优化。 4
    发表于 03-08 11:58 0次下载

    基于KingView的SQL数据查询设计_杨洋

    基于KingView的SQL数据查询设计_杨洋
    发表于 01-17 19:57 0次下载

    SQL语句怎么搞定跨实例查询

    这个SQL的语法完全兼容MySQL,只是在From的表名前面带上DBLink。所以,业务方只需要使用DMS跨数据库查询SQL便可轻松解决拆库之后的跨库查询难题,业务基本无需改造。
    发表于 11-03 10:22 5593次阅读

    数据库:为什么SQL使用了索引,却还是慢查询

    经常有同学问我,我的一个SQL语句使用了索引,为什么还是会进入到慢查询之中呢?今天我们就从这个问题开始来聊一聊索引和慢查询
    发表于 08-10 16:09 880次阅读
    数据库:为什么<b class='flag-5'>SQL</b>使用了索引,却还是慢<b class='flag-5'>查询</b>?

    SQL查询优化是怎么回事

    查询 (Subquery)的优化一直以来都是 SQL 查询优化中的难点之一。 关联子查询的基本执行方式类似于 Nested-Loop,但是这种执行方式的效率常常低到难以忍受。 当数据
    的头像 发表于 02-01 13:55 1831次阅读
    <b class='flag-5'>SQL</b>子<b class='flag-5'>查询</b>优化是怎么回事

    简述Django查询生成原始SQL查询的3种方法

    我们使用Django ORM使查询数据库变得非常容易,但是如果我们知道幕后发生了什么或对某些Django查询执行了什么SQL查询,对我们提升查询
    的头像 发表于 06-04 16:36 1744次阅读

    SQL语句和自定义查询在导入包中可用

    在高级任务编辑器模式下,您可以选择要使用的操作-自己键入和编辑任何复杂性的SQL语句(执行命令)或通过我们的可视化查询构建器(执行查询)创建自定义查询。新模式对于
    的头像 发表于 04-16 09:13 902次阅读

    一文终结SQL查询优化

    查询(Subquery)的优化一直以来都是 SQL 查询优化中的难点之一。关联子查询的基本执行方式类似于 Nested-Loop,但是这种执行方式的效率常常低到难以忍受。
    的头像 发表于 04-28 14:19 477次阅读
    一文终结<b class='flag-5'>SQL</b>子<b class='flag-5'>查询</b>优化

    sql查询语句大全及实例

    SQL(Structured Query Language)是一种专门用于数据库管理系统的标准交互式数据库查询语言。它被广泛应用于数据库管理和数据操作领域。在本文中,我们将为您详细介绍SQL
    的头像 发表于 11-17 15:06 647次阅读

    sql关联查询中的主表和从表

    SQL关联查询是数据库中非常重要的一项操作,用于联合多个表中的数据,并根据指定的条件进行筛选和整合,从而得到更加丰富和准确的结果集。在关联查询中,主表和从表起着不同的作用,通过合理的关联方式和条件
    的头像 发表于 11-23 11:41 500次阅读

    oracle执行sql查询语句的步骤是什么

    Oracle数据库是一种常用的关系型数据库管理系统,具有强大的SQL查询功能。Oracle执行SQL查询语句的步骤包括编写SQL语句、解析
    的头像 发表于 12-06 10:49 416次阅读

    查询SQL在mysql内部是如何执行?

    我们知道在mySQL客户端,输入一条查询SQL,然后看到返回查询的结果。这条查询语句在 MySQL 内部到底是如何执行的呢?本文跟大家探讨一下哈,我们先来看下MySQL基本架构~
    的头像 发表于 01-22 14:53 164次阅读
    <b class='flag-5'>查询</b><b class='flag-5'>SQL</b>在mysql内部是如何执行?