首页 文章 精选 留言 我的

精选列表

搜索[数仓建模],共10009篇文章
优秀的个人博客,低调大师

数仓的等待视图中,为什么会有Hashjoin-nestloop

本文分享自华为云社区《GaussDB(DWS)等待视图之Hashjoin-nestloop》,作者:Arrow0lf。 1. 业务场景 众所周知,GaussDB(DWS)中有3种常见的join方式:HashJon/MergeJoin/NestLoop 但在有一些场景中,等待视图中等待状态会显示为:HashJoin-nestloop,如下图所示。这种表示什么含义? 2. 基本原理 为了明白该状态的原因,首先思考如下场景:当业务侧两张大表join时,如果由于未做analyze或统计信息不准,导致build hash的一侧选择了大表,且该表在join列上重复值很多,会导致hashjoin时内存膨胀,当内存不足时,hashjon算子会下盘,但是由于join列上存在大量重复值,下盘文件无法有效分裂,此时,如果将整个文件都读取到内存中,会导致内存占用很高,出现内存过载,导致其他业务内存不足报错。 为了解决该场景,在向量化hashjoin时,当使用内表创建的hash表过大导致内存不足时,不再强制进行hashjoin,会通过内外表交换或执行nestloop使查询平稳进行,防止出现内存报错,此时,等待视图状态为“HashJoin-nestloop” 上述特性通过hashjoin_spill_strategy参数控制,默认为0,取值范围为0-6的整数,详情可以参考产品文档(8.1.2及以上版本),简单来讲: 取值为0或5,hashjoin时会先尝试内外表交换,如果仍然内存占用高,会选择nestloop; 取值为1或6,hashjoin时会先尝试内外标交换,如果仍然内存占用高,会强行执行hashjoin; 取值为2,hashjoin行为和原本的行为保持一致,即使内存不够,也会强制执行hashjoin 3. 业务影响 当等待视图出现Hashjoin-nestloop时,可能会导致原来内存占用高,单能执行成功的语句,在被转换成nestloop后,可能会短时间执行不出来。尤其是当数据量变化较大,统计信息差异较大时,容易出现执行计划非最优场景下的性能劣化。 4. 解决方法 如果出现上述HashJoin-nestloop时间长,导致业务超时的情况。可以将参数hashjoin_spill_strategy设置为2进行规避。不再进行内外表交换或执行nestloop,使业务行为与之前的行为保持一致。 在内存充裕的场景下,可以全局设置为2。 点击关注,第一时间了解华为云新鲜技术~

优秀的个人博客,低调大师

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

本文分享自华为云社区《【调优实践】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 | 点击关注,第一时间了解华为云新鲜技术~

优秀的个人博客,低调大师

深入理解大数据数仓工具 Apache Hive 底层原理

作者:幻好 概述 通过学习 Apache Hive 基础知识和 HIve SQL 后,能够了解到 Hive 是将 SQL 语句通过底层转换生成 MR 程序进行工作,为了能对 Hive 能有一个更加深入的认识,还需要深入理解 Hive SQL 的执行原理。 本文将通过对于 Hive 底层执行原理的深入解读,帮助读者对于 Hive 的作用有更深入的理解。 Hive 底层原理 在使用 Hive 进行日常需求开发使用后,能够大概了解 Hive 是将 SQL 语句通过底层转换生成 MR 程序进行工作,为了能对 Hive 能有一个更加深入的认识,还需要深入理解 Hive SQL 的执行原理。 Hive 执行架构 Hive 是基于 Hadoop 进行交互工作的,所以根据 Hive 的整个工作的流程可以有以下架构图: 核心组件 根据上图,可知 Hive 工作执行中包含以下5个组件: UI(用户界面):可看作我们提交 SQL 语句的命令行界面。 DRIVER(驱动程序):接收查询的组件。该组件实现了会话句柄的概念。 COMPILER(编译器):负责将 SQL 转化为平台可执行的执行计划。对不同的查询块和查询表达式进行语义分析,并最终借助表和从 META STORE 查找的分区元数据来生成执行计划。 META STORE(元数据库):存储 Hive 中各种表和分区的所有结构信息。 EXECUTION ENGINE(执行引擎):负责提交 COMPILER 阶段编译好的执行计划到不同的平台上。 工作流程 结合上图,Hive 的正常工作流程分为以下步骤: Step 1:用户通过 UI 界面编写 SQL 提交会调用 DRIVER 的接口; Step 2:DRIVER 接收查询任务后,会为查询创建会话句柄,并将查询发送到 COMPILER 生成执行计划; Step3:编译器从 META STORE 中获取本次查询所需要的元数据; Step 4:查询到对应的元数据,会用于对查询树中的表达式进行类型检查,以及基于查询谓词修建分区; Step 5:编译器生成的执行计划是分阶段的 DAG(有向无环图),其中的阶段可能是 map/reduce 作业,也可能是一个元数据或在 HDFS 上的操作。最后将生成的计划发给 DRIVER,如果是 map/reduce 作业,该计划包括 map operator trees 和一个 reduce operator tree,执行引擎将会把这些作业发送给 MapReduce; Step 6:执行引擎将这些阶段提交给适当的组件。在每个 task(mapper/reducer) 中,从 HDFS 文件中读取与表或中间输出相关联的数据,并通过相关算子树传递这些数据。最终这些数据通过序列化器写入到一个临时 HDFS 文件中(如果不需要 reduce 阶段,则在 map 中操作)。临时文件用于向计划中后面的 map/reduce 阶段提供数据。 Step 7:最终的临时文件将移动到相关表的位置,确保不读取脏数据(文件重命名在 HDFS 中是原子操作)。 Step 8:对于用户的查询,临时文件的内容由执行引擎直接从 HDFS 读取,然后通过 Driver 发送到 UI。 Hive SQL编译原理 Hive 最重要的工作就是将 SQL 语句编译成 MapReduce 的过程,而编译 SQL 的过程是在 COMPILER(编译器)中完成的。编译转换的过程主要分为以下几个阶段: 语法解析:通过语言识别工具 Antlr 定义 SQL 的语法规则,完成 SQL 词法,语法解析,将 SQL 转化为抽象语法树 AST Tree; 语义解析:遍历 AST Tree,抽象出查询的基本组成单元 QueryBlock; 生成逻辑执行计划:遍历 QueryBlock,翻译为执行操作树 OperatorTree; 优化逻辑执行计划:逻辑层优化器进行 OperatorTree 变换,合并 Operator,达到减少 MapReduce Job,减少数据传输及 shuffle 数据量; 生成物理执行计划:遍历 OperatorTree,翻译为 MapReduce 任务; 优化物理执行计划:物理层优化器进行 MapReduce 任务的变换,生成最终的执行计划。 编译案例分析 Hive SQL 编译转换为 MR 程序的过程从概念上理解起来比较抽象,为了更好的理解直接结合一个简单的查询案例进行分析: select * from hivedb.sys_user where id = '1001'; 第一阶段:语法解析 通过 Antlr 定义的 sql 语法规则,将相关 sql 进行词法、语法解析,转化为抽象语法树 AST Tree: ABSTRACT SYNTAX TREE: TOK_QUERY TOK_FROM TOK_TABREF TOK_TABNAME hivedb sys_user TOK_INSERT TOK_DESTINATION TOK_DIR TOK_TMP_FILE TOK_SELECT TOK_SELEXPR TOK_ALLCOLREF TOK_WHERE = TOK_TABLE_OR_COL id '1001' -第二阶段:**语义解析 ** 遍历 AST Tree,抽象出查询的基本组成单元 QueryBlock: AST Tree 生成后由于其复杂度依旧较高,不便于翻译为 mapreduce 程序,需要进行进一步抽象和结构化,形成 QueryBlock。 QueryBlock 是一条 SQL 最基本的组成单元,包括三个部分:输入源,计算过程,输出。简单来讲一个 QueryBlock 就是一个子查询。 QueryBlock 的生成过程为一个递归过程,先序遍历 AST Tree ,遇到不同的 Token 节点(理解为特殊标记),保存到相应的属性中。 -第三阶段:**生成逻辑执行计划 ** 遍历 QueryBlock,翻译为执行操作树 OperatorTree: Hive 最终生成的 MapReduce 任务,Map 阶段和 Reduce 阶段均由 OperatorTree 组成。 基本的操作符包括: TableScanOperator SelectOperator FilterOperator JoinOperator GroupByOperator ReduceSinkOperator Operator 在 Map Reduce 阶段之间的数据传递都是一个流式的过程。每一个 Operator 对一行数据完成操作后之后将数据传递给 childOperator 计算。 由于 Join/GroupBy/OrderBy 均需要在 Reduce 阶段完成,所以在生成相应操作的 Operator 之前都会先生成一个 ReduceSinkOperator,将字段组合并序列化为 Reduce Key/value, Partition Key。 -第四阶段:优化逻辑执行计划 Hive 中的逻辑查询优化可以大致分为以下几类: 投影修剪 推导传递谓词 谓词下推 将 Select-Select,Filter-Filter 合并为单个操作 多路 Join 查询重写以适应某些列值的 Join 倾斜 -第五阶段:**生成物理执行计划 ** 生成物理执行计划即是将逻辑执行计划生成的 OperatorTree 转化为 MapReduce Job 的过程,主要分为下面几个阶段: 对输出表生成 MoveTask 从 OperatorTree 的其中一个根节点向下深度优先遍历 ReduceSinkOperator 标示 Map/Reduce 的界限,多个 Job 间的界限 遍历其他根节点,遇过碰到 JoinOperator 合并 MapReduceTask 生成 StatTask 更新元数据 剪断 Map 与 Reduce 间的 Operator 的关系 -第六阶段:优化物理执行计划 Hive 中的物理优化可以大致分为以下几类: 分区修剪(Partition Pruning) 基于分区和桶的扫描修剪(Scan pruning) 如果查询基于抽样,则扫描修剪 在某些情况下,在 map 端应用 Group By 在 mapper 上执行 Join 优化 Union,使 Union 只在 map 端执行 在多路 Join 中,根据用户提示决定最后流哪个表 删除不必要的 ReduceSinkOperators 对于带有 Limit 子句的查询,减少需要为该表扫描的文件数 对于带有 Limit 子句的查询,通过限制 ReduceSinkOperator 生成的内容来限制来自 mapper 的输出 减少用户提交的 SQL 查询所需的 Tez 作业数量 如果是简单的提取查询,避免使用 MapReduce 作业 对于带有聚合的简单获取查询,执行不带 MapReduce 任务的聚合 重写 Group By 查询使用索引表代替原来的表 当表扫描之上的谓词是相等谓词且谓词中的列具有索引时,使用索引扫描 通过以上6个阶段,SQL 就被解析映射成了集群上的 MapReduce 任务。 总结 本文主要介绍 Apache Hive 工作的底层原理,通过对于 Hive SQL 执行的工作流程到底层执行过程的解析能够帮助读者更深入的理解 Hive 的作用。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册