案例技术parallel cution zhs深入理解Oracle_第1页
案例技术parallel cution zhs深入理解Oracle_第2页
案例技术parallel cution zhs深入理解Oracle_第3页
案例技术parallel cution zhs深入理解Oracle_第4页
案例技术parallel cution zhs深入理解Oracle_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、深入理解 Oracle 的并行执行(上)作者: 目录:Oracle 的并行执行2术语说明2测试环境和数据2并行初体验3串行执行3并行执行4小结6生产者-­消 模型6Broadcast 分发, 一次数据分发6生产者-­消 模型工作原理7小结9如何阅读并行执行计划9HASH 分发方式, 两次数据分发10小结12Replicate, Broadcast 和 Hash 的选择12Hash 分发, 有时是唯一合理的选择12使用 broadcast 分发, 糟糕的性能14小结, Broadcast 和 Hash 分发的陷阱16Partition Wise Join, 消除分发的额外开销

2、17Partition Wise Join, 不需要数据分发17当 DoP 大于分区数时, Partition Wise Join 发生19小结20数据倾斜对不同分发方式的影响20Replicate 方式, 不受数据倾斜的影响21Hash 分发, 数据倾斜造成执行倾斜22小节24HASH JOIN BUFFERED, 连续 hash 分发时执行计划中的阻塞点24使用 Broadcast 分发, 没有阻塞点24连续 hash 分发, 执行计划出现阻塞点25小结27Hash join 和过滤27关于 过滤27过滤对 hash join 性能的改进28使用 过滤时的性能28不使用 过滤时的性能29H

3、ASH 分发时过滤的生成, 传输, 合并与使用30小结31并行执行计划中典型的串行点31Rownum, 导致并行执行计划效率低下32自定义 PL/SQL 函数没有设置 parallel_enable, 导致无法并行34并行 DML, 没有 enable parallel dml, 导致 DML 操作无法并行36小节37总结37致谢38作者简介38Oracle 的并行执行Oracle 的并行执行是一种分而治之的. 执行一个 sql 时, 分配多个并行进程同时执行数据扫描, 连接以及聚合等操作, 使用的资源, 得到更快的 sql 响应时间. 并行执行是充分利用硬件资源, 处理大量数据时的 技术.在

4、本文中, 在一个简单的星型模型上, 我会使用大量例子和 sql monitor 报告, 力求以最直观简单的方式, 向读者阐述并行执行的内容:· Oracle 并行执行为什么使用生产者-­消模型.· 如何阅读并行执行计划.· 不同的数据分发 别适合什么样的场景.· 使用 partition wise join 和并行执行的组合提高性能.· 数据倾斜会对不同的分发方式带来什么影响.· 由于生产者-­消 模型的限制, 执行计划中可能出现阻塞点.·过滤是如何提高并行执行性能的.· 现实世界中, 使用并行

5、执行时最常见的问题.术语说明:1. S: 时间秒.2. K: 数量一千.3. M: 数量一百万, 或者时间分钟.4. DoP: Degree of Parallelism, 并行执行的并行度.5. QC: 并行的 Query Coordinator.6. PX 进程: Parallel Execution Slaves.7. AAS: Average active session, 并行执行时平均的活动会话数.8. 分发: pq distribution method, 并行执行的分发方式, replicate, broadcast, hash 和 adaptive分发等 4 种方式, 其中

6、adaptive 分发是 12c 引入的的新特性, 我将在本篇文章阐述.9. Hash join 的左边: 驱动表, the build side of hash join, 为 .10. Hash join 的右边: 被驱动表, the probe side of hash join, 为大表.11. 过滤: bloom filter, 一种内存数据结构, 用于一个元素是否属于一个集合.测试环境和数据Oracle 版本为 12.1.0.2.2, 两个节点的 RAC, 硬件为 Exadata X3-­8.这是一个典型的星型模型, 事实表 lineorder 有 3 亿行, 维度表 p

7、art/customer 分别包含 1.2M和 1.5M 行, 3 个表都没有进行分区, lineorder 大小接近 30GB.表名行数lineorder300005811part1200000customer1500000selectowner seg_owner,segment_name seg_segment_name, round(bytes/1048576,2) SEG_MBfrom38dba_segments whereowner = 'SID'and segment_name in ('LINEORDER','PART','

8、;CUSTOMER')/OWNER SEGMENT_NAME SEGMENT_TYPESEG_MBSIDLINEORDERTABLE30407.75SIDCUSTOMERTABLE168SIDPARTTABLE120本篇文章所有的测试, 除非特别的说明, 我关闭了 12c 的 adaptive plan 特性, 参数optimizer_adaptive_features 被默认设置为 false. Adaptive 相关的特性如 cardinality feedback, adaptive distribution method, adaptive join 都启用. 如果检查执行计划

9、的 outline 数据, 你会发现 7 个优化器相关的隐含参数被设置为关闭状态. 事实上, 12c 优化器因为引入 adaptive plan 特 性, 比以往版本复杂得多, 剖析 12c 的优化器的各种新特性, 我觉得非常具有性, 或许我会在另一篇文章里尝试一下JJselect * from table(dbms_xplan.display_cursor('77457qc9a324k',0,outline);.Outline Data/*+*/BEGIN_OUTLINE_DATA IGNORE_OPTIM_EMBEDDED_HINTS OPTIMIZER_FEATURES_

10、ENABLE('12.1.0.2') DB_VERSION('12.1.0.2')OPT_PARAM('_optimizer_use_feedback' 'false') OPT_PARAM('_px_adaptive_dist_method' 'off') OPT_PARAM('_optimizer_dsdir_usage_control' 0) OPT_PARAM('_optimizer_adaptive_plans' 'false') OPT_P

11、ARAM('_optimizer_strans_adaptive_pruning' 'false') OPT_PARAM('_optimizer_gather_feedback' 'false') OPT_PARAM('_optimizer_nlj_hj_adaptive_join' 'false') OPT_PARAM('optimizer_dynamic_sampling' 11)ALL_ROWS END_OUTLINE_DATA并行初体验串行执行以下 sql 对 custome

12、rs 和 lineorder 连接之后, 计算所有订单的全部利润. 串行执行时不使用parallel hint:select /*+ monitor */ sum(lo_revenue)fromlineorder, customer wherelo_custkey = c_custkey;串行执行时, sql 执行时间为 1.5 分钟, db time 为 1.5 分钟. 执行计划有 5 行, 一个用户进程工作完成了对 customer, lineorder 两个表的扫描, hash join, 聚合以及返回数据的所有操作. 此时AAS(average active sessions)为 1,

13、 sql 执行时间等于 db time. 几乎所有的 db time 都为 db cpu, 72% 的 cpu 花在了第二行的 hash join 操作. 因为测试机器为一台 Exadata X3-­8, 30GB 的 IO 请求在一秒之内处理完成. Cell offload Efficiency 等于 87%意味着经过节点扫描, 过滤不需要的列, 最终返回计算节点的数据大小只有 30GB 的 13%.并行执行使用 hint parallel(4), 指定 DoP=4 并行执行同样的 sql:select /*+ monitor parallel(4)*/ sum(lo_revenu

14、e)fromlineorder, customer wherelo_custkey = c_custkey;SQL 执行时间为 21s, db time 为 1.4 分钟. DoP=4, 在两个实例上执行. 执行计划从 5 行增加为 9 行, 从下往上分别多了PX BLOCK ITERATOR, SORT AGGREGATE, PX SEND QC(RANDOM)和PX COORDINATOR这四个操作.其中 3 到 8 行的操作为并行处理, sql 的序为: 每个 PX 进程扫描维度表 customer(第 6 行), 以数据块地址区间作为 (第 7 行)扫描四分之一的事实表 lineord

15、er(第 8 行), 接着进行 hash join(第 5 行), 然后对连接之后的数据做预先聚合(第 4 行), 最后把结果给 QC(第三行). QC 接收数据(第 2 行)之后, 做进一步的汇总(第 1 行), 最后返回数据(第 0 行).SQL 执行时间比原来快了 4 倍, 因为最消耗时间的操作, 比如对 lineorder 的扫描, hash join 和聚合, 我们使用 4 个进程并行处理, 因此最终 sql 执行时间为串行执行的 1/4. 另一方面, db time 并没有明显下降, 并行时 1.4m, 串行时为 1.5m, 从系统的角度看, 两次执行消耗的系统资源是一 样的.Do

16、P=4 时, 因为没有涉及数据的分发(distribution), QC 只需分配一组 PX 进程, 四个 PX 进程分别为实例 1 和 2 的 p000/p0001. 我们可以从系统上查看这 4 个 PX 进程. 每个 PX 进程消耗大致一样的db time, CPU 和 IO 资源. AAS=4, 这是最理想的情况, 每个 PX 进程完成同样的工作量, 一直保持活跃. 没有串行点, 没有并行执行倾斜.AAS=4, 查看活动时, 为了更展示活动, 注意点掉”CPU Cores”这个复选框.在 Linux 系统上显示这四个 PX 进程.oracleexa01db01 sidney$ ps -e

17、f | egrep "p0001_SSB"oracle208881 4 2014 ?18:50:59 ora_p000_SSB1oracle208921 4 2014 ?19:01:29 ora_p001_SSB1 oracleexa01db01 sidney$ ssh exa01db02 'ps -ef | egrep "p0001_SSB"' oracle569101 4 2014 ?19:01:03 ora_p000_SSB2oracle569121 4 2014 ?18:53:30 ora_p001_SSB2小结本节的例子中, D

18、oP=4, 并行执行时分配了 4 个 PX 进程, 带来 4 倍 的性能提升. SQL monitor 报告包含了并行执行的总体 和各种细节, 比如 QC, DoP, 并行执行所在的实例, 每个 PX 进程消耗的资源, 以及执行 SQL 时 AAS. , 深入讨论并行执行的生产者-­消 模型.生产者-消 模型在上面并行执行的例子中, 每个 px 进程都会扫描一遍维度表 customer, 然后扫描事实表 lineorder 进行 hash join. 这时没有数据需要进行分发, 只需要分配一组 px 进程. 这种 replicate 维度表的行为, 是 12c 的新特性, 由参数_p

19、x_replication_enabled .更常见情况是并行执行时, QC 需要分配两组 PX 进程, 互为生产者和消, 协同工作, 完成并行执行计划. 架构图1如下:Broadcast 分发, 一次数据分发为了举例说明两组 px 进程如何协作的, 设置_px_replication_enabled 为 false. QC 会分配两组 PX进程, 一组为生产者, 一组为消.见下图, 此时 sql 执行时间为 23s, 执行时间变慢了 2s, db time 仍为 1.5 分钟.最大的变化来自执行计划, 现在执行计划有 12 行. 增加了对 customer 的并行扫描PX BLOCK ITE

20、RATOR(第 8 行), 分发PX SEND BROADCAST和接收PX RECEIVE. 执行计划中出现了两组 PX 进程, 除了之前蓝色的多人标志, 现在出现了红色的多人标志. 此时, SQL 的序为:1 自白皮书 Parallel Execution with Oracle Database 12c Fundamentals: 130766.pdf1. 4 个红色的 PX 进程扮演生产者角色, 扫描维度表 customer, 把数据通过 broadcast 的 发给每一个扮演消 的蓝色 PX 进程. 因为 DoP=4, 每一条被扫描出来的被 了 4 份, 从 sql monitor

21、的第 9 行, customer 扫描返回 1.5m 行数据, 第 8 行的分发和第 7 行的接受之时, 变成了 6m 行, 每个作为消的蓝色 px 进程都持有了一份完整包含所有custome的数据, 并准备好第 5 行 hash join 的 build table.2. 4 个作为消的蓝色 PX 进程, 以数据块地址区间为扫描事实表 lineorder(第 10/11 行); 同时和已经持有的 customer 表的数据进行 hash join(第 5 行), 然后对满足 join 条件的数据做预聚合(第 4 行), 因为我们的目标是对所有 lo_revenue 求和, 聚合之后每个 PX

22、 进程只需输出一个总数.3. 4 个蓝色的 PX 进程反过来作为生产者, 把聚合的数据发给消 QC(第 3 行和第 2 行). 由 QC对接收到 4 行做最后的聚合, 然后返回给用户.4. 使用 broadcast 的分发方式, 只需要把 customer 的数据广播给每个消. Lineorder 的数不需要重新分发. 因为 lineorder 的数据量比 customer 大的多, 应该避免对 lineorder 的数据进行分发, 这种执行计划非常适合星型模型的数据.观察 sql monitor 报告中 Parallel 下的 , 红色的 PX 进程为实例 1、2 上的 p002/p003

23、进程, 蓝色的 PX 进程为 p000/p001 进程, 因为蓝色的 PX 进程负责扫描事实表 lineorder, hash join 和聚合, 所以消耗几乎所有的 db time.生产者-消 模型工作原理并行 之后, 可以通过视图 V$PQ_TQSTAT, 验证以上描述的执行过程.1. 实例 1、2 上的 p002/p003 进程作为生产者, 几乎平均扫描 customer 的 1/4 , 把每一条记录广播给 4 个消 PX 进程, 发送的数之和为 6m 行. 通过 table queue 0(TQ_ID=0), 每个作为消 的 p000/p001 进程, 接收了完整的 1.5m 行 cu

24、stomer , 接收的数之和为6m 行.2. 实例 1、2 上的 p000/p0001 进程作为生产者, 通过 table queue 1(TQ_ID=1), 把聚合的一条结果 发给作为消 的 QC. QC 作为消, 接收了 4 行.SELECTdfo_number, tq_id, server_type, instance, process, num_rowsFROMV$PQ_TQSTAT ORDER BYdfo_number DESC, tq_id, server_type desc, instance, process;DFO_NUMBERTQ_IDSERVER_TYPEINSTANC

25、EPROCESSNUM_ROWS10Producer1P002146193210Producer1P003150189210Producer2P002157571210Producer2P003146046410Consumer1P000150000010Consumer1P001150000010Consumer2P000150000010Consumer2P001150000011Producer1P000111Producer1P001111Producer2P000111Producer2P001111Consumer1QC413 rows selected.那么, 以上的输出中, D

26、FO_NUMBER 和 TQ_ID 这两列表示什么意思呢?1. DFO 代表 Data Flow Operator, 是执行计划中可以并行执行的操作. 一个 QC 代表一棵 DFO 树(tree), 包含多个 DFO; 同一个 QC 中所有并行操作的 DFO_NUMBER 是相同的, 此例中, 所有DFO_NUMBER 为 1. 执行计划包含多个 QC 的例子也不少见, 比如使用 union all 的语句, union all 每个分支都是的 DFO 树, 不同的 DFO 树之间可以并行执行. 本篇文章仅讨论执行计划只有一个 QC 的情况.2. TQ 代表 table queue, 用以 P

27、X 进程之间或者和 QC 通信连接. 以上执行计划中, table queue 0 为 PX 进程之间的连接, table queue 1 为 PX 进程和 QC 之间的连接. 生产者通过 table queue 分发数据, 消从 table queue 接收数据. 不同的 table queue 编号, 代表了不同的数据分发. 通过 table queue, 我们可以理解 Oracle 并行执行使用生产者-­消模型的本质:· 同一棵 DFO 树中, 最多只有两组 PX 进程. 每个生产者进程都一个和每个消进程的连接, 每个 PX 进程和 QC 都接. 假设 DoP=n,

28、连接总数为(n*n + 2*n), 随着 n 的增长, 连接总数会爆炸型增长. Oracle 并行执行设计时, 采用生产者和消模型, 考虑到连接数的复杂度, 每个 DFO 最多只分配两组 PX 进程. 假设 DoP=100 时, 两组 PX 进程之间的连接总数为 10000. 假设可以分配三组 PX 进程一起完成并行执行计划, 那么三 组 PX 之间连接总数会等于 1 百万, 维护这么多连接, 是一个不可能的任务.· 同一棵 DFO 树中, 两组 PX 进程之间, 同一时间只一个活跃的数据分发. 如果执行路径很长, 数据需要多次分发, 两组 PX 进程会变换生产者消角色, 相互协作,

29、 完成所有并行操作. 每次数据分发, 对应的 table queue 的编号不同. 一个活跃的数据分发过程, 需要两组 PX 进程都参与, 一组为生产者发送数据, 一组为消接收数据. 因为一个DFO 里最多只有两组 PX 进程, 意味着, PX 进程之间, 同一时间只能有一个活跃的数据分发. 如果 PX 进程在执行计划中需要多次分发数据, 可能需要在执行计划一些阻塞点, 比如 BUFFER SORT 和 HASH JOIN BUFFERED 这两个操作, 保证上一次的数据分发完成之后, 才开始下一次分发. 在后面的章节, 我将会说明这些阻塞点带来什么影响. 这个例子中, table queue

30、 0 和 1 可以同时工作是因为: table queue 0 是两组 PX 进程之间的链接, table queue 1 为 PX 进程和 QC 之间的连接, table queue 0 与 table queue 1 是相互的, 因此可以同时进行.· PX 进程之间或者与 QC 的连接至少一个(单节点下至多三个, RAC 环境下至多四个)消息缓冲区用于进程间数据交互, 该消息缓冲区默认在 Large pool 中分配(如果没有配置Large pool 则在 Shared pool 中分配). 多个缓冲区是为了实现异步通信, 提高性能.· 每个消息缓冲区的大小由参数 pa

31、rallel_execution_message_size , 默认为 16k。· 当两个进程都在同一个节点的时候, 通过在 Large pool(如果没有配置 Large pool 则Shared pool)中传递和接收消息缓冲进行数据交互. 当两个进程位于不同节点时. 通过RAC 心跳网络进行数据交互, 其中一方接收的数据需要缓本地 Large pool(如果没有配置 Large pool 则 Shared pool)里面.小结为了说明并行执行的生产者-­消模型是如何工作的, 我使用了 broadcast 分发, QC 分配两组 PX 进程, 一组为生产者, 一组为消.

32、 QC 和 PX 进程之间, 两组 PX 进程之间通过 table queue 进行 数据分发, 协同完成整个并行执行计划. 视图 V$PQ_TQSTAT 了并行执行过程中, 数据是如何分发的. 通过对 DFO, table queue 的描述, 我阐述生产者-­消模型的工作原理和通信过程, 或许有些描述对你来说过于突然, 不用担心, 后面的章节我会通过的例子来辅助理解.如何阅读并行执行计划Table queue 的编号代表了并行执行计划中, 数据分发的顺序. 理解执行计划中的并行操作是如何被执行的, 原则很简单: 跟随 Table queue 的顺序.通过 sql monitor

33、报告 sql 的序, 需要结合 name 列的 table queue 名字比如:TQ10000(代表 DFO=1, table queue 0),:TQ10001(代表 DFO=1, table queue 1), 还有 PX 进程的颜色,进行确定.下面的例子为 dbms_xplan.display_cursor 的输出. 对于并行执行计划, 会多出来三列:1. TQ 列: 为 Q1:00 或者 Q1:01, 其中 Q1 代表第一个 DFO, 00 或者 01 代表 table queue 的编号.a. ID 79 的操作的 TQ 列为 Q1,00, 该组 PX 进程, 作为生产者首先执行,

34、 然后通过broadcast 的分发方式, 把数据发给消.b. ID 1011, 36 的操作的 TQ 列为 Q1,01, 该组 PX 进程作为消接受 customer 的数据之后, 扫描 lineorder, hash join, 聚合之后, 又作为生产者通过 table queue 2 把数据发给 QC.2. In-­out 列: 表明数据的和分发.· PCWC: parallel combine with child.· PCWP: parallel combine with parent.· P-­>P: parallel to

35、parallel.· P-­>S: parallel to Serial.3. PQ Distribute 列: 数据的分发方式. 此执行计划中, 我们使用了 broadcast 的方式, 下面的章节我会讲述其他的分发方式.HASH 分发方式, 两次数据分发除了 broadcast 分发方式, 另一种常见的并行分发 hash. 为了观察使用 hash 分发时 sql 的执行情况, 我对 sql 使用 pq_distribute hint.select /*+ monitor parallel(4) leading(customer lineorder) use_has

36、h(lineorder) pq_distribute(lineorder hash hash) */sum(lo_revenue)fromlineorder, customer wherelo_custkey = c_custkey;使用 hash 分发, sql 的执行时间为 29s, db time 为 2.6m. 相对于 broadcast 方式, sql 的执行时间和 db time 都增加了大约 40%.执行计划如下, 执行计划为 14 行, 增加了对 lineorder 的 hash 分发, 第 11 行的PX SEND HASH对 3 亿行数据通过 hash 函数分发, 第 10

37、 行的PX RECEIVE 通过 table queue 1 接收 3 亿行数据, 这两个操作消耗了 38%的 db cpu. 这就是为什么 SQL 执行时间和 db time 变长的. 此时, SQL 的执行顺序为:1. 红色的 PX 进程作为生产者, 并行扫描 customer(第 89 行), 对于连接键 c_custkey 运用 hash 函数, 根据每行的 hash 值, 通过 table queue 0, 发给 4 个蓝色消的其中一个(第 7 行). Hash 分发方式并数据, sql monitor 报告的第 69 行, actual rows 列都为 1.5m.2. 红色的 P

38、X 进程作为生产者, 并行扫描 lineorder(第 1213 行), 对于连接键 lo_custkey 运用同样的 hash 函数, 通过 table queue 1, 发给 4 个蓝色消的其中一个(第 11 行). 同样的 hash 函数保证了 customer 和 lineorder 相同的连接键会发给同一个消, 保证 hash join 结果的正确. 因为 3 亿行数据都需要经过 hash 函数计算, 然后分发(这是进程间的通信, 或者需要通过 RAC 心跳网络通信), 这些巨大的额外开销, 就是增加 38% cpu 的.3. 4 个蓝色的 PX 进程作为消接收了 customer

39、的 1.5M 行 (第 6 行), 和 lineorder 的 3 亿行 (第 10 行), 进行 hash join(第 5 行), 预聚合(第 4 行).4.4 个蓝色的 PX 进程反过来作为生产者,通过 table queue 2, 把聚合的数据发给消QC(第 3行和第 2 行). 由 QC 对接收到 4 行做最后的聚合, 然后返回给用户(第 1 和 0 行).观察 sql monitor 报告中 Parallel 下的 , 红色的 px 进程为实例 1、2 上的 p002/p003 进程, 蓝色的 PX 进程为 p000/p001 进程. 作为生产者的红色 PX 进程负责扫描事实表 l

40、ineorder, 对 3 亿行数据进行 hash 分发, 占了超过 1/3 的 db time.因为涉及 3 亿行数据的分发和接收, 作为生产者的红色 PX 进程和作为消的蓝色 PX 进程需要同时活跃, SQL monitor 报告中的 activity 显示大部分时间, AAS 超过并行度 4, 意味这两组 PX 进程同时工作. 不像 replicate 或者 broadcast 分发时, AAS 为 4, 只有一组 PX 进程保持活跃.并行之后, 通过视图 V$PQ_TQSTAT, 进一步验证以上描述的执行过程. 并行执行过程涉及 3个 table queue 0/1/2, V$PQ_T

41、QSTAT 包含 21 行.1. 实例 1、2 上的 p002/p003 进程作为生产者, 平均扫描 customer 的 1/4 , 然后通过 table queue 0(TQ_ID=0), 发给作为消的 p000/p001 进程. 发送和接收的 customer 之和都为1.5m.· 发送的 数: 1500000 = 365658 + 364899 + 375679 + 393764· 接收的 数: 1500000 = 374690 + 374924 + 375709 + 3746772. 实例 1、2 上的 p002/p0003 进程作为生产者, 平均扫描 lineo

42、rder 的 1/4 , 通过 table queue 1(TQ_ID=1), 发给作为消的 p000/p001 进程. 发送和接收的 lineorder 之和都为300005811.· 发送的 数: 300005811 = 74987629 + 75053393 + 74979748 + 74985041· 接收的 数: 300005811 = 74873553 + 74968719 + 75102151 + 750613883. 实例 1、2 上的 p000/p0001 进程作为生产者, 通过 table queue 2(TQ_ID=2), 把聚合的一条结果 发给作为消

43、 的 QC. QC 作为消, 接收了 4 行.SELECTdfo_number, tq_id, server_type, instance, process, num_rowsFROMV$PQ_TQSTAT ORDER BYdfo_number DESC, tq_id, server_type desc, instance, process;DFO_NUMBERTQ_ID SERVER_TYPEINSTANCE PROCESSNUM_ROWS10 Producer1 P00236565810Producer1P00336489910Producer2P00237567910Producer2P

44、00339376410Consumer1P00037469010Consumer1P00137492410Consumer2P00037570910Consumer2P00137467711Producer1P0027498762911Producer1P0037505339311Producer2P0027497974811Producer2P0037498504111Consumer1P00074873553Consumer1P00Consumer2P00Consumer2P00Producer1P00Producer1P001112Producer2P000112Producer2P00

45、1112Consumer1QC421 rows selected.小结我们观察 hash 分发时 sql 的并行执行过程. Hash 分发与 broadcast 最大的区分在于对 hash join 的两 进行分发. 这个例子中, 对 lineorder 的 hash 分发会增加明显的 db cpu. , 我将使用另一个例子, 说明 hash 分发适用的场景.Replicate, Broadcast 和 Hash 的选择我们已经测试过 replicate, broadcast, 和 hash 这三种分发方式.1. Replicate: 每个 PX 进程重复扫描 hash join 的左边, b

46、uffer cache 被用来缓存 hash join 左边的 , 减少重复扫描所需的物理读. 相对于 broadcast 分发, replicate 方式只需一组 PX 进程. 但是 replicate 不能替换 broadcast 分发. 因为 replicate 仅限于 hash join 左边是表的情况, 如果hash join 的左边的结果集来自其他操作, 比如 join 或者视图, 那么此时无法使用 replicate.2. Broadcast 分发: 作为生产者的 PX 进程通过广播的方式, 把 hash join 左边的结果集分发给每个作为消 的 PX 进程. 适用于 hash

47、 join 左边结果集比右边小得多的场景, 比如星型模型.3. Hash 分发的本质: 把 hash join 的左边和右边(两个数据源), 通过同样 hash 函数重新分发, 切分为 N 个工作单元(假设 DoP=N), 再进行 join, 目的是减少 PX 进程进行 join 操作时, 需要连接的数据量. Hash 分发的代价需要对 hash join 的两进行分发. 对于 customer 连接lineorder 的例子, 因为维度表 customer 的数据量比事实表 lineorder 小得多, 对 customer 进行 replicate 或者 broadcast 分发显然是更选

48、择, 因为这两种方式不用对 lineorder 进行重新分发. 如果是两个大表 join 的话, join 操作会是整个执行计划的瓶颈所在, hash 分发是唯一合适的方式. 为了减低 join 的代价, 对 hash join 左边和右进行 hash 分发的代价是可以接受的.Hash 分发, 有时是唯一合理的选择我们使用 lineorder 上的自连接来演示, 为什么有时 hash 分发是唯一合理的选择. 测试的 SQL 如下:select /*+ monitor parallel(4)*/ sum(lo1.lo_revenue)fromlineorder lo1, lineorder lo

49、2 wherelo1.lo_orderkey = lo2.lo_orderkey;SQL 执行时间为 2.4 分钟, db time 为 10.5 分钟.优化器默认选择 hash 分发方式, 执行计划为 14 行, 结构与之前的 Hash 分发的例子是一致的. 不同的是, 第 5 行的 hash join 消耗了 73%的 db time, 使用了 9GB 的临时表空间, 表空间的 IO 占 12% 的 db time. 大约 15%的 db time 用于 Lineorder 的两次 hash 分发和接收, 相对上一个例子的占38% 比例, 这两次 HASH 分发的整体影响降低了一倍多.红色

50、的 PX 进程为实例 1、2 上的 p002/p003 进程, 蓝色的 PX 进程为 p000/p001 进程.作为生产者的红色 PX 进程占总 db time 的 15%左右.SQL 执行开始, 对 lineorder 两次 hash 分发时, AAS 大于 4, 分发完成之后, 只有蓝色的 PX 进程进行hash join 操作, AAS=4.从 V$PQ_TQSTAT 视图可以确认, 对于 lineorder 的两次分发, 通过 table queue 0 和 1, 作为消 的 4 个 PX 进程接收到的两次数据是一样的, 保证重新分发影响 join 结果的正确性. 每个蓝色 PX 进程

51、需要 hash join 的左边和右边均为 3 亿行数据的 1/4, 通过 hash 分发, 3 亿行连接3 亿行的工作平均的分配四个 PX 进程各自处理, 每个 PX 进程处理 75M 行连接75M 行.SELECTdfo_number, tq_id, server_type, instance, process, num_rowsFROMV$PQ_TQSTAT ORDER BYdfo_number DESC, tq_id, server_type desc, instance, process;DFO_NUMBERTQ_IDSERVER_TYPEINSTANCEPROCESSNUM_ROW

52、S10Producer1P0027505572510Producer1P0037497745910Producer2P0027499527610Producer2P0037497735110 Consumer1P0074998419Consumer1P00Consumer2P0074976974Consumer2P00Producer1P007498679811Producer1P0037498526811Producer2P0027498488311Producer2P0037504886211 Consumer1P007499841911 Consumer1P00Consumer2P007

53、4976974Consumer2P00Producer1P00112Producer1P001112Producer2P000112Producer2P001112Consumer1QC421 rows selected.使用 broadcast 分发, 糟糕的性能对于 lineorder, lineorder 的自连接, 如果我们使用 broadcast 分发, 会出现什么情况呢? 我们测试一下:select /*+ monitor parallel(4) leading(lo1 lo2) use_hash(lo2)pq_distribute(lo2 broadcast none) */su

54、m(lo1.lo_revenue) fromlineorder lo1, lineorder lo2 wherelo1.lo_orderkey = lo2.lo_orderkey;使用 broadcase 分发, SQL 的执行时间为 5.9 分钟, db time 为 23.8 分钟. 相比 hash 分发, 执行时间和 db time 都增加了接近 1.5 倍.红色的 PX 进程作为生产者, 对 lineorder 进行并行扫描之后, 3 亿行通过 table queue 0 广播给4 个作为消的蓝色 PX 进程(第 69 行), 相当于了 4 份, 每个蓝色的 PX 进程都接收了 3 亿行 . 这次 broadcast 分发消耗了 11%的 db time, 因为需要每行传输给每个蓝色 PX 进程, 消耗的 db cpu 比使用 hash 分发时两次 hash 分发所消耗的还多.每个蓝色 PX 进程进行 hash join 的数据变大了, hash join 的左边为 3 亿行数据, has

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论