后浪云OceanBase教程:OceanBase MERGE

MERGE 算子用于将源表中的数据行以更新或插入的方式合并到目标表中。

OceanBase 数据库支持的 MERGE 算子包括 MERGE 和 MULTI PARTITION MERGE。

MERGE

MERGE 算子用于合并数据表单个分区中的数据。

如下例所示,Q1 查询将 src_tbl 表中的数据行合并到 t1 表中,对于 src_tbl 中的每一条数据行按照如下方式进行合并:

  • 当 t1 中存在满足 t1.c1=src_tbl.c1 条件的数据行:

    • 如果满足 src_tbl.c2 > '100',则执行更新操作,将 t1.c2 的值置为 src_tbl.c2 的值(目标表中的每一行只会更新一次)。

    • 如果不满足 src_tbl.c2 > '100',则不执行更新操作。

  • 当 t1 中不存在满足 t1.c1 = src_tbl.c1 条件的数据行:

    • 如果满足 src_tbl.c1 > 10,则执行插入操作,向 t1 中插入 (src_tbl.c1,src_tbl.c2)

    • 如果不满足 src_tbl.c1 > 10,则不指定插入操作。


    obclient>CREATE TABLE src_tbl (c1 INT PRIMARY KEY, c2 VARCHAR2(10));
    Query OK, 0 rows affected (0.12 sec)
    
    obclient>CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 VARCHAR2(10));
    Query OK, 0 rows affected (0.12 sec)
    
    obclient>CREATE TABLE t2 (c1 INT PRIMARY KEY, c2 VARCHAR2(10)) PARTITION BY HASH(c1) 
             PARTITIONS 10;
    Query OK, 0 rows affected (0.12 sec)
    
    Q1: 
    obclient>EXPLAIN MERGE INTO t1 USING src_tbl ON (t1.c1 = src_tbl.c1)
            WHEN MATCHED THEN 
            UPDATE SET t1.c2 = src_tbl.c2 WHERE src_tbl.c2 > '100'
            WHEN NOT MATCHED THEN 
            INSERT (t1.c1, t1.c2)  VALUES (src_tbl.c1,src_tbl.c2) WHERE src_tbl.c1 > 10\G;
    *************************** 1. row ***************************
    Query Plan:
    ===============================================
    |ID|OPERATOR         |NAME   |EST. ROWS|COST  |
    -----------------------------------------------
    |0 |MERGE            |       |100001   |100001|
    |1 | MERGE OUTER JOIN|       |100001   |219005|
    |2 |  TABLE SCAN     |SRC_TBL|100000   |61860 |
    |3 |  TABLE SCAN     |T1     |100000   |61860 |
    ===============================================
    
    Outputs & filters:
    -------------------------------------
      0 - output([column_conv(DECIMAL,PS:(38,0),NOT NULL,SRC_TBL.C1)], [column_conv(VARCHAR,utf8mb4_bin,length:10,NULL,SRC_TBL.C2)]), filter(nil),
          columns([{T1: ({T1: (T1.C1, T1.C2)})}]), partitions(p0),
          update([T1.C2=column_conv(VARCHAR,utf8mb4_bin,length:10,NULL,SRC_TBL.C2)]),
          match_conds([T1.C1 = SRC_TBL.C1]), insert_conds([SRC_TBL.C1 > 10]),
          update_conds([SRC_TBL.C2 > '100']), delete_conds(nil)
      1 - output([SRC_TBL.C1], [SRC_TBL.C2], [T1.C1], [T1.C1 = SRC_TBL.C1], [T1.C2]), filter(nil),
          equal_conds([T1.C1 = SRC_TBL.C1]), other_conds(nil)
      2 - output([SRC_TBL.C1], [SRC_TBL.C2]), filter(nil),
          access([SRC_TBL.C1], [SRC_TBL.C2]), partitions(p0)
      3 - output([T1.C1], [T1.C2]), filter(nil),
          access([T1.C1], [T1.C2]), partitions(p0)

    其中,OUTER JOIN 是合并功能实现时依赖的一次联接操作,使用 MERGE 算子时,一定会在 source_table 和 target_table 上做一次外联接,目的是为了区分哪些行是匹配的,哪些是不匹配的。

    执行计划展示中的 outputs & filters 详细列出了 MERGE 算子的输出信息如下:

    信息名称

    含义

    output

    该算子输出的表达式。

    filter

    该算子上的过滤条件。

    由于示例中 MERGE 算子没有设置 filter,所以为 nil。

    columns

    插入操作涉及的数据表的列。

    partitions

    插入操作涉及到的数据表的分区。

    update

    更新操作中所有的赋值表达式。

    match_conds

    源表和目标表进行匹配的条件。

    insert_conds

    插入操作需要满足的条件。

    update_conds

    更新操作需要满足的条件。

    delete_conds

    删除操作需要满足的条件。

MULTI PARTITION MERGE

MULTI PARTITION MERGE 算子用于合并数据表多个分区中的数据。

如下例所示,Q2 查询将 src_tbl 表中的数据行合并到分区表 t2 表中,对于 src_tbl 中的每一条数据行按照如下方式进行合并:

  • 当 t2 中存在满足 t2.c1 = src_tbl.c1 条件的数据行:

    • 执行更新操作,将 t2.c2 的值置为 substr(src_tbl.c2, 1, 5) 的值(目标表中的每一行只会更新一次)。

    • 更新完成后,如果满足 t2.c2 > '80000' ,则删除对应的数据行。

  • 当 t2 中不存在满足 t2.c1 = src_tbl.c1 条件的数据行,执行插入操作,向 t2 中插入 (src_tbl.c1, src_tbl.c2)


Q2: 
obclient>EXPLAIN MERGE INTO t2 USING SRC_TBL ON (t2.c1 = src_tbl.c1)
        WHEN MATCHED THEN 
        UPDATE SET t2.c2 = SUBSTR(src_tbl.c2, 1, 5) 
        DELETE WHERE t2.c2 > '80000'
        WHEN NOT MATCHED THEN 
        INSERT (t2.c1, t2.c2) VALUES (src_tbl.c1,src_tbl.c2)\G;
*************************** 1. row ***************************
Query Plan:
============================================================

|ID|OPERATOR                      |NAME    |EST. ROWS|COST   |
--------------------------------------------------------------
|0 |MULTI PARTITION MERGE         |        |100000   |100000 |
|1 | PX COORDINATOR               |        |100000   |956685 |
|2 |  EXCHANGE OUT DISTR          |:EX10001|100000   |899889 |
|3 |   MERGE OUTER JOIN           |        |100000   |899889 |
|4 |    EXCHANGE IN DISTR         |        |100000   |90258  |
|5 |     EXCHANGE OUT DISTR (PKEY)|:EX10000|100000   |61860  |
|6 |      TABLE SCAN              |SRC_TBL |100000   |61860  |
|7 |    SORT                      |        |1000000  |5447108|
|8 |     PX PARTITION ITERATOR    |        |1000000  |618524 |
|9 |      TABLE SCAN              |T2      |1000000  |618524 |
==============================================================

Outputs & filters:
-------------------------------------
  0 - output([column_conv(DECIMAL,PS:(38,0),NOT NULL,SRC_TBL.C1)], [column_conv(VARCHAR,utf8mb4_bin,length:10,NULL,SRC_TBL.C2)]), filter(nil),
      columns([{T2: ({T2: (T2.C1, T2.C2)})}]), partitions(p[0-9]),
      update([T2.C2=column_conv(VARCHAR,utf8mb4_bin,length:10,NULL,SUBSTR(SRC_TBL.C2, 1, 5))]),
      match_conds([T2.C1 = SRC_TBL.C1]), insert_conds(nil),
      update_conds(nil), delete_conds([T2.C2 > '80000'])
  1 - output([SRC_TBL.C1], [SRC_TBL.C2], [T2.C1], [T2.C1 = SRC_TBL.C1], [T2.C2]), filter(nil)
  2 - output([SRC_TBL.C1], [SRC_TBL.C2], [T2.C1], [T2.C1 = SRC_TBL.C1], [T2.C2]), filter(nil), dop=1
  3 - output([SRC_TBL.C1], [SRC_TBL.C2], [T2.C1], [T2.C1 = SRC_TBL.C1], [T2.C2]), filter(nil),
      equal_conds([T2.C1 = SRC_TBL.C1]), other_conds(nil)
  4 - output([SRC_TBL.C1], [SRC_TBL.C2]), filter(nil)
  5 - (#keys=1, [SRC_TBL.C1]), output([SRC_TBL.C1], [SRC_TBL.C2]), filter(nil), is_single, dop=1
  6 - output([SRC_TBL.C1], [SRC_TBL.C2]), filter(nil),
      access([SRC_TBL.C1], [SRC_TBL.C2]), partitions(p0)
  7 - output([T2.C1], [T2.C2]), filter(nil), sort_keys([T2.C1, ASC]), local merge sort
  8 - output([T2.C1], [T2.C2]), filter(nil)
  9 - output([T2.C1], [T2.C2]), filter(nil),
      access([T2.C1], [T2.C2]), partitions(p[0-9])

上述示例的执行计划展示中的 outputs & filters 详细列出了 MULTI PARTITION MERGE 算子的输出信息,字段的含义与 MERGE 算子相同。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/284464.html<

(0)
管理的头像管理
上一篇2025-05-14 10:21
下一篇 2025-05-14 10:23

相关推荐

  • 云服务器和云虚拟主机怎么选?云服务器和虚拟主机区别

    云服务器适合业务增长快、需弹性扩展的场景,而云虚拟主机适合预算有限、技术门槛低的小型静态网站或测试环境,二者核心区别在于资源独享性与运维复杂度,核心差异解析:从底层架构到使用体验很多人容易混淆这两者,觉得它们都是“买空间建站”,它们的底层逻辑完全不同,云服务器(ECS)就像是你租了一整栋别墅,水电网络独立,你想……

    2026-06-29
    0
  • 赣州智慧旅游招聘是真的吗?赣州旅游人才招聘信息

    中级岗位(3-5年经验)月薪范围通常在6000-10000元,这类岗位需要独立负责项目模块,如独立运营一个抖音账号,或维护一个景区小程序的功能迭代,具备成功案例的候选人议价能力较强,高级岗位(5年以上经验)月薪范围通常在10000-20000元,部分核心管理岗可达更高,这类人才需要具备战略规划能力,如制定整个景……

    2026-06-29
    0
  • 赣州智能物联网车位锁如何管理?智能车位锁管理系统多少钱

    赣州智能物联网车位锁管理的核心在于通过云端平台实现远程控锁、状态实时监控及自动计费,彻底解决传统车位“被占难管”与“找位难”的痛点,在赣州这样的城市,随着机动车保有量的持续增长,老旧小区、商业综合体以及私人固定车位的资源矛盾日益凸显,传统的机械地锁或简易遥控锁,不仅操作繁琐,更无法实现数据化管理,引入智能物联网……

    2026-06-29
    0
  • 赣州智能消防栓好用吗,智能消防栓多少钱一个

    赣州智能消防栓通过物联网技术实现实时监测与远程报警,能显著降低火灾响应时间并提升城市消防安全管理水平,是目前智慧城市建设中不可或缺的基础设施,赣州智能消防栓的核心价值与应用场景传统消防栓往往存在“看不见、摸不着、用不了”的痛点,在赣州这样地形复杂、老城区与新城区并存的区域,传统设施的管理难度极大,智能消防栓的出……

    2026-06-29
    0
  • 云服务器和物理机到底有啥区别?

    云服务器本质上是虚拟化资源池中的弹性实例,而传统物理服务器是独占的硬件实体,前者胜在弹性与运维便捷,后者强在物理隔离与性能稳定,具体选择取决于业务对成本、扩展性及安全合规的权衡,很多人初次接触服务器时,容易把“云服务器”和“传统物理服务器”混为一谈,觉得它们都是用来跑网站或存数据的盒子,这两者的底层逻辑完全不同……

    2026-06-29
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注