首页 > 数据库 >数仓调优实践丨SQL改写消除相关子查询

数仓调优实践丨SQL改写消除相关子查询

时间:2023-12-25 11:01:01浏览次数:32  
标签:数仓 16KB t2 t1 调优 SQL c2 c1 查询

本文分享自华为云社区《【调优实践】SQL改写消除相关子查询》,作者: 门前一棵葡萄树 。

一、子查询

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] |      5 |      5 |            

点击关注,第一时间了解华为云新鲜技术~

 

标签:数仓,16KB,t2,t1,调优,SQL,c2,c1,查询
From: https://www.cnblogs.com/huaweiyun/p/17925679.html

相关文章

  • MYSQL varchar和nvarchar一些学习
    MYSQLvarchar和nvarchar一些学习背景先试用utfmb3的格式进行一下简单验证注意脚本都是一样的.createdatabasezhaobsh;usezhaobsh;createtablezhaobsh(zhaobshvarcharvarchar(30),zhaobshnvarcharnvarchar(30));insertintozhaobshvalues('123abc','1......
  • 大数据从业者必知必会的Hive SQL调优技巧 | 京东云技术团队
    摘要:在大数据领域中,HiveSQL被广泛应用于数据仓库的数据查询和分析。然而,由于数据量庞大和复杂的查询需求,HiveSQL查询的性能往往不尽人意。本文针对HiveSQL的性能优化进行深入研究,提出了一系列可行的调优方案,并给出了相应的优化案例和优化前后的SQL代码。通过合理的优化策略和技......
  • MySQL 查看版本的 5 种方法
    mysql数据库查看版本号SELECTVERSION();linux查看版本号mysqld-Vmysql-version 方法一:登录MySQL每次通过mysql客户端连接服务器之后,都会显示一个欢迎信息,里面包含了服务器的版本:mysql-urootEnterpassword:******WelcometotheMySQLmonitor.Commandsend......
  • 第81讲:清理MySQL Binlog二进制日志的方式
    1.清理Binlog二进制日志的依据Binlog日志非常重要,但是占用的磁盘空间也很大,我们也需要定期的去清理二进制日志,在MySQL数据库中,提供了自动清理Binlog日志的参数,根据指定的天数,保留n天内的Binlog日志,也可以手动人为删除。在手动删除Binlog日志时,要切记不要使用rm-rf直接删除Binlog......
  • MySQL 主从故障排查
    MySQL主从复制是一种常见的数据库架构,用于提高数据库的可用性和性能。但是,在实际应用中,主从故障是难免的。本文详细介绍一套MySQL主从故障排查方案。一确认主从状态首先要确定主从复制的状态,可以通过执行以下命令来检查:1)SHOWMASTERSTATUS;命令用于显示主库的状态信息,包括以下列......
  • 无涯教程-PostgreSQL - Triggers(触发器)
    PostgreSQL触发器是数据库回调函数,当发生指定的数据库事件时,它们会自动执行。Triggers-语法创建trigger的基本语法如下-CREATETRIGGERtrigger_name[BEFORE|AFTER|INSTEADOF]event_nameONtable_name[--Triggerlogicgoeshere....];在这里,event_name可以......
  • Oracle基础SQL整理:创建表空间、创建用户、赋予DBA权限、建表
    创建表空间CREATEtablespacefrdemodatafile'/tmp/frdemo.dbf'SIZE128mautoextendONNEXT100mmaxsize1024m;创建用户及绑定表空间CREATEUSERfruserIDENTIFIEDBYfinereportDEFAULTtablespacefrdemo;给用户赋予dba权限GRANTdbaTOfruser;创建表CREATETABLEt_o......
  • SQL Server Management Studio (SSMS)教程:创建数据库create database、创建表create t
    USEmasterGOIFNOTEXISTS(SELECTnameFROMsys.databasesWHEREname=N'TutorialDB')CREATEDATABASE[TutorialDB]GOUSE[TutorialDB]--Createanewtablecalled'Customers'inschema'dbo'--Dropthetable......
  • mysql开发包安装
    1.下载MySQL的yum源安装包,例如:wgethttp://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm2.安装yum源安装包,例如:sudoyumlocalinstallmysql57-community-release-el7-7.noarch.rpm3.安装mysql-community-devel-5.7.44,例如:sudoyuminstallmysql-community-d......
  • SQL的left()函数
    LEFT()是SQL中常用的字符串函数之一,用于从字符串的左侧获取指定数量的字符。以下是关于LEFT()函数的详细介绍:使用场景:截取字符串中的前几个字符:当你需要从字符串的左侧获取一定数量的字符时,可以使用LEFT()函数。处理固定长度的字符串:当数据表中的数据长度是固定的,并且你......