【数据写入】达梦数据库(dm8)merge into写入时序数据速度慢的问题处理

简介

本文记录一次处理达梦数据库写入时序数据库性能优化的问题

场景

从以往MYSQL/KINGBASE迁移到DM过程中,发现时序数据消费速度较低,kafka形成严重积压,代码除了数据库写入层进行了修改,其余未做任何变化,那么可以快速定位到问题是写入问题。具体场景为,当时序数据消费时,按照点编码更新DM实时表的value值,若点编码不存在则插入该新编码对应的数据。

相较于普通场景,我们一般会使用先查询,后考虑插入还是更新的方式,但对于大量数据来说,需要优化插入逻辑,即一次性完成此操作:存在则更新、不存在则插入,相较于MYSQL/KINGBASE的insert into on confilict 方式,DM使用的是merge into 方法:

复制代码
MERGE INTO XXXX t1
        USING (
        <foreach collection="list" item="item" index="index" separator="UNION ALL">
            SELECT #{item.id} as id,
            #{item.createDate} as create_date,
            now() as update_date
            FROM DUAL
        </foreach>
        ) t2 ON (t1.id = t2.id)
        when matched then
        update set
	   t1.XXX = t2.XXXX,
        t1.create_date = t2.create_date,
        t1.update_date = t2.update_date
        WHEN NOT MATCHED THEN
        INSERT (id,XXX,create_date,update_date)
        VALUES (t2.id,XXX,now(),t2.update_date)

代码可以正常运行,但是该方式数据写入存在较大问题,从日志可以看出,插入数据上千条,所耗费时间达到数据秒,不满足业务需求

解决方案

通过与达梦团队对接优化方案,最后得到了更优的做法,即写入数据先进入临时表,merge的时候使用临时表数据进行merge,从而避免在写入过程中构建大批量临时数据项

1、创建临时表(表结构与插入表一致,去除ID/唯一性等限制信息)

复制代码
CREATE TEMPORARY table mqt_temp (
    "ID" VARCHAR(64 CHAR),
    XXXX..
    "CREATE_DATE" TIMESTAMP(0),
    "UPDATE_DATE" TIMESTAMP(0)
    ) ON COMMIT DELETE ROWS;

2、插入逻辑由一次性插入分为2个步骤,即先插入临时表,再merge

复制代码
  this.baseDao.insertTmp(updateDataList);
  this.baseDao.merge();

3、相关mybatis语句

(1)插入临时表mybatis

复制代码
<insert id="insertTmp">
    INSERT INTO mqt_temp (
    id, XXX, create_date, update_date
    )
    VALUES
    <foreach collection="list" item="item" separator=",">
        (
        #{item.id},
        XXX....
        #{item.dataTime},
        #{item.createDate},
        NOW()
        )
    </foreach>
</insert>

(2)新merge语句(使用临时表)

复制代码
<insert id="updateBatch2" parameterType="java.util.List">
    MERGE INTO XXX 最终插入数据表
    USING (
    SELECT *
    FROM mqt_temp
    ) s ON (t.id = s.id)
    when matched then
    update set
    t.XX = s.XXX,
    t.data_time = s.data_time,
    t.update_date = s.update_date
    WHEN NOT MATCHED THEN
    INSERT (id,XXXX, create_date, update_date)
    VALUES (s.id,XXX, now(), now())
</insert>

总结

使用临时表优化后,数据插入效率提升数倍左右

相关推荐
heartbeat..4 小时前
Spring AOP 全面详解(通俗易懂 + 核心知识点 + 完整案例)
java·数据库·spring·aop
麦聪聊数据6 小时前
MySQL并发与锁:从“防止超卖”到排查“死锁”
数据库·sql·mysql
AC赳赳老秦7 小时前
DeepSeek 私有化部署避坑指南:敏感数据本地化处理与合规性检测详解
大数据·开发语言·数据库·人工智能·自动化·php·deepseek
YMatrix 官方技术社区7 小时前
YMatrix 存储引擎解密:MARS3 存储引擎如何超越传统行存、列存实现“时序+分析“场景性能大幅提升?
开发语言·数据库·时序数据库·数据库架构·智慧工厂·存储引擎·ymatrix
辞砚技术录8 小时前
MySQL面试题——索引2nd
数据库·mysql·面试
linweidong8 小时前
C++thread pool(线程池)设计应关注哪些扩展性问题?
java·数据库·c++
欧亚学术9 小时前
突发!刚刚新增17本期刊被剔除!
数据库·论文·sci·期刊·博士·scopus·发表
黑白极客10 小时前
怎么给字符串字段加索引?日志系统 一条更新语句是怎么执行的
java·数据库·sql·mysql·引擎
大厂技术总监下海10 小时前
数据湖加速、实时数仓、统一查询层:Apache Doris 如何成为现代数据架构的“高性能中枢”?
大数据·数据库·算法·apache
LeenixP11 小时前
RK3576-Debian12删除userdata分区
linux·运维·服务器·数据库·debian·开发板