Doris删除数据工具

文章目录

    • 概要
    • 整体架构流程
    • 技术名词解释
    • 技术细节
    • 小结

概要

对于Doris的 Unique 模型,在删除数据的时候只能根据key删除,如果使用其他条件就会报错

整体架构流程

先获得表的key,然后在通过输入的条件获得key的所有值,最后通过key的值拼接删除语句,调用线程删除。

技术名词解释

  • jsqlparser :SQL解析工具,能将字符串解析出SQL的表,值,条件等
  • HikariCP :数据库连接池
  • 单例模式:单例模式调用数据库连接

技术细节

  • 多线程:使用线程池开启线程,也可以使用分页线程
  • 时间显示:时间显示使用无符号的时间格式

小结

具体实现代码如下:

package org.example;

import java.sql.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static org.example.SqlParserExample.getTableName;

public class Main {

    public static void main(String[] args) throws Exception {
        initLogRecord.initLog();
        System.out.println("================================================================");
        Connection conn = HikariConfigs.HikariConn();
        // Statement stmt = conn.createStatement();
        Scanner scanner = new Scanner(System.in);
        System.out.println("===========================请输入删除的语句=========================");
        String sql = scanner.nextLine();
        String where = "";
        if (sql.indexOf("where") > 0) {
            where = sql.substring(sql.indexOf("where"));
        } else if (sql.indexOf("WHERE") > 0) {
            where = sql.substring(sql.indexOf("WHERE"));
        }
        System.out.println("=======================获取WHERE条件=============================");
        System.out.println(where);
        String table = getTableName(sql);
        String getKey = "select * from information_schema.columns where TABLE_NAME = ? ";
        PreparedStatement ptmt_getKey = conn.prepareStatement(getKey);
        ptmt_getKey.setString(1, table);
        ResultSet rs = ptmt_getKey.executeQuery();
        List<String> key = new ArrayList<>();
        Map<String, String> key_type = new HashMap<>();
        System.out.println("=======================获取KEY==================================");
        while (rs.next()) {
            if (rs.getString("column_key").equals("UNI")) {
                key.add(rs.getString("column_name"));
                key_type.put(rs.getString("column_name"), rs.getString("DATA_TYPE"));
                System.out.println(rs.getString("column_name") + "  " + rs.getString("column_key"));
            }
        }

        System.out.println("=======================拼接key==================================");
        String column = "";
        for (String s : key) {
            if (!Objects.equals(column, "")) {
                column = column + "," + s;
            } else {
                column = s;
            }
        }
        System.out.println(column);

        // 拼接SELECT 语句
        String newSQL = "SELECT " + column + " FROM " + table + " " + where;
        PreparedStatement pstm_getkeyvalue = conn.prepareStatement(newSQL);
        rs = pstm_getkeyvalue.executeQuery();
        List<Map<String, String>> values = new ArrayList<>();
        while (rs.next()) {
            Map<String, String> map = new HashMap<>();
            for (String x : key) {
                map.put(x, rs.getString(x));
            }
            values.add(map);
        }
        // for (int i =0 ;i< values.size();i++){
        // System.out.println(values.get(i));;
        // }

        // 循环拼接删除的where 条件
        StringBuilder delete_where;
        String delete_sql;
        List<String> delete_sqls = new ArrayList<>();
        for (Map<String, String> x : values) {
            delete_where = new StringBuilder();
            for (String y : x.keySet()) {
                if (delete_where.length() > 0) {
                    // 时间格式的拼接
                    if (key_type.get(y).equals("datetime")) {
                        LocalDateTime date = LocalDateUtils.parseLocalDateTime(x.get(y),
                                LocalDateUtils.DATETIME_PATTERN);
                        String str = LocalDateUtils.format(date, LocalDateUtils.UNSIGNED_DATETIME_PATTERN);
                        delete_where.append(" AND ").append(y).append("=").append("'").append(str).append("'");
                    } else {
                        delete_where.append(" AND ").append(y).append("=").append("'").append(x.get(y)).append("'");
                    }
                } else {
                    if (key_type.get(y).equals("datetime")) {
                        LocalDate date = LocalDateUtils.parseLocalDate(x.get(y), LocalDateUtils.DATETIME_PATTERN);
                        String str = LocalDateUtils.format(date, LocalDateUtils.UNSIGNED_DATETIME_PATTERN);
                        delete_where = new StringBuilder(y + "=" + "'" + str + "'");
                    } else {
                        delete_where = new StringBuilder(y + "=" + "'" + x.get(y) + "'");
                    }
                }
            }
            delete_sql = "";
            delete_sql = "DELETE FROM " + table + " WHERE " + delete_where;
            delete_sqls.add(delete_sql);
            // System.out.println("删除语句:"+ delete_sql);
            // if (dels.executeUpdate(delete_sql)>0){
            // i++;
            // System.out.println("=======================删除成功=======================");
            // }else{
            // System.out.println("!!!!!!!!!!!!!!!!!删除失败!!!!!!!!!!!!!!!!!");
            // j++;
            // }
        }
        conn.close();

        // 使用线程执行sql
        System.out.println("=====================  需要删除数据的总数为: " + delete_sqls.size() + "  =================");
        System.out.println("======================  请确认是否删除? yes or no=====================");
        String is_delete = scanner.nextLine();
        if (!is_delete.equals("yes")) {
            return;
        }

        // ExecutorService executor = Executors.newFixedThreadPool(10); // 创建一个固定大小的线程池
        // AtomicInteger successCount = new AtomicInteger(0); // 原子计数器,用于记录成功执行的SQL数量
        // AtomicInteger failureCount = new AtomicInteger(0); // 统计失败次数
        // long start = System.currentTimeMillis();
        // executor.submit(() -> {
        //     try (Connection connection = HikariConfigs.HikariConn();) {
        //         for (int i = 0; i < delete_sqls.size(); i++) {
        //             Statement statement = connection.createStatement();
        //             String deletesql = delete_sqls.get(i);
        //             System.out.println("!!!正在删除数据:" + deletesql);
        //             // int updateCount = statement.executeUpdate(deletesql);
        //             // if (updateCount > -1) {
        //             //     successCount.incrementAndGet(); // 如果删除成功,增加本地计数器

        //             // } else {
        //             //     failureCount.incrementAndGet();// 如果删除失败
        //             // }

        //             statement.addBatch(deletesql);
        //             successCount.incrementAndGet(); // 如果删除成功,增加本地计数器
        //             if (i % 500 == 0) {
        //                 statement.executeBatch();
        //             }
        //         }
        //     } catch (SQLException e) {
        //         e.printStackTrace();
        //     } catch (InterruptedException ex) {
        //         ex.printStackTrace();
        //     }

        // });

        // executor.shutdown(); // 关闭线程池
        // executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); // 等待所有任务完成
        // long end = System.currentTimeMillis();

        
        AtomicInteger successCount = new AtomicInteger(0); // 原子计数器,用于记录成功执行的SQL数量
        AtomicInteger failureCount = new AtomicInteger(0); // 统计失败次数

        int size = delete_sqls.size();
        int theadCount = 10;
        int splitCount = size / theadCount + (size % theadCount != 0 ? 1 : 0); //计算分拆数量,向上取整
        final CountDownLatch cdl = new CountDownLatch(theadCount);// 定义线程数量
        long starttime = System.currentTimeMillis();
        for (int k = 1; k <= theadCount; k++) {
            final int beign = (k - 1)  * splitCount;
            final int end = (k * splitCount) > size ? size : k * splitCount;
            if(beign >= end) break;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Connection con = JDBCTools.getConnection();
                    try {
                        Statement st = con.createStatement();
                        for (int i = 0; i < delete_sqls.size(); i++) {
                            String deletesql = delete_sqls.get(i);
                            System.out.println("!!!正在删除数据:" + deletesql);
                            int count = st.executeUpdate(deletesql);
                            if (count > -1) {
                                successCount.incrementAndGet();
                            }else{
                                failureCount.incrementAndGet();
                            }
                        }
                        cdl.countDown(); // 执行完一个线程,递减1
                    } catch (Exception e) {
                    } finally {
                        try {
                            con.close();
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
        try {
            cdl.await();    //前面线程没执行完,其他线程等待,不往下执行
            long spendtime=System.currentTimeMillis()-starttime;
            System.out.println( theadCount+"个线程花费时间:"+spendtime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endtime = System.currentTimeMillis();
        System.out.println("已完成删除");
        System.out.println("成功删除数据 " + successCount + " 条");
        System.out.println("删除失败 " + failureCount + " 条");
        System.out.println("消耗的时间为(毫秒):" + (endtime - starttime));
        System.out.println("消耗的时间为(秒):" + TimeUnit.MILLISECONDS.toSeconds(endtime - starttime));

    }
}

完整的项目git地址:Doris工具

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/498748.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从国内外IT人的差异谈如何破除35岁魔咒

本来想写篇关于DBA如何破除35岁魔咒的文章&#xff0c;但发现整个IT从业人员都面临着35岁魔咒&#xff0c;例如互联网的从业人员的平均年龄只有26岁。但国外同行的职业生命却长得多&#xff0c;这里我们通过分析一下国内外IT人的差异来探讨如何破除35岁魔咒。 我们和丑国的IT…

【数据挖掘】实验5:数据预处理(2)

验5&#xff1a;数据预处理&#xff08;2&#xff09; 一&#xff1a;实验目的与要求 1&#xff1a;熟悉和掌握数据预处理&#xff0c;学习数据清洗、数据集成、数据变换、数据规约、R语言中主要数据预处理函数。 二&#xff1a;实验知识点总结 1&#xff1a;数据集成是将多个…

Ubuntu通过分用户进行多版本jdk配置

前言&#xff1a;本文内容为实操记录&#xff0c;仅供参考&#xff01; linux安装jdk参考&#xff1a;http://t.csdnimg.cn/TeECj 出发点&#xff1a;最新的项目需要用jdk17来编译&#xff0c;就把服务器的jdk版本升级到了17&#xff0c;但是有一些软件例如nexus还需要jdk1.8进…

自动化测试 —— Pytest fixture及conftest详解

前言 fixture是在测试函数运行前后&#xff0c;由pytest执行的外壳函数。fixture中的代码可以定制&#xff0c;满足多变的测试需求&#xff0c;包括定义传入测试中的数据集、配置测试前系统的初始状态、为批量测试提供数据源等等。fixture是pytest的精髓所在&#xff0c;类似u…

Linux系统使用Docker部署MinIO结合内网穿透实现公网访问本地存储服务

文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对象存储服务器&#xff0c;可以在各种环境中运行&#xff0c;例如本地、Docker容器、Kubernetes集群等。它兼…

pulsar: kafka on pulsar之把pulsar当kafka用

一、下载协议包&#xff08;要和pulsar版本比较一致&#xff09; https://github.com/streamnative/kop/releases?q2.8.0&expandedtrue二、在pulsar的根目录创建一个protocols目录&#xff0c;将上述包放到这个目录里 三、编辑broker.conf(如果是集群)或者standalone.con…

学点儿数据库_Day12_数据库SQL练习题

0 版本与工具 mysql-8.0.31 Navicat Premium 16 每做一题&#xff0c;选中相应代码运行即可&#xff0c;很方便 1 建表 create table goods (goods_id mediumint(8) unsigned primary key auto_increment,goods_name varchar(120) not null default ,cat_id smallint(5) un…

cesium vue 绘制标记实体(撒点),监听鼠标左击事件

添加实体 const viewer new Cesium.Viewer(cesiumContainer, {})viewer.entities.add()查看实体 const viewer new Cesium.Viewer(cesiumContainer, {}) const billboard viewer.entities.add({...})viewer.zoomTo(billboard)删除实体 根据实体删除 if (billboard.value…

C#手术麻醉信息系统全套商业源码,自主版权,支持二次开发 医院手麻系统源码

手术麻醉信息系统是HIS产品的中的一个组成部分&#xff0c;主要应用于医院的麻醉科&#xff0c;属于电子病历类产品。医院麻醉监护的功能覆盖整个手术与麻醉的全过程&#xff0c;包括手术申请与排班、审批、安排、术前、术中和术后的信息管理提供支持。 手术麻醉信息系统可与EM…

《QT实用小工具·一》电池电量组件

1、概述 项目源码放在文章末尾 本项目实现了一个电池电量控件&#xff0c;包含如下功能&#xff1a; 可设置电池电量&#xff0c;动态切换电池电量变化。可设置电池电量警戒值。可设置电池电量正常颜色和报警颜色。可设置边框渐变颜色。可设置电量变化时每次移动的步长。可设置…

重学SpringBoot3-SpringBoot可执行JAR的原因

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-SpringBoot可执行JAR的原因 Spring Boot可执行JAR的结构打包运行JAR 包内部结构 工作原理优点总结 Spring Boot 的一个核心特性是它的可执行 JAR&#x…

stm32之GPIO寄存器

文章目录 1 背景2 GPIO寄存器的类型2.1 端口配置寄存器2.2 设置/清除寄存器和位清除寄存器 3 总结 1 背景 C51单片机在进行数据的输入输出时&#xff0c;是直接操作与外部引脚关联的内部寄存器&#xff0c;例如&#xff0c;当设置P2_1为0时&#xff0c;就是将外部引脚的P21引脚…

Composer常见错误解决指南 ️

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

基于java疫情防控系统

疫情防控系统 伴随着新年的喜悦&#xff0c;2020年春节之际一场新冠疫情席卷了全球&#xff0c;但是在中国领导人的英明领导之下我国的疫情很快得到了控制&#xff0c;但是因为欧美等国家对疫情的不够重视&#xff0c;仍然有很多的境外疫情携带者会出入我国&#xff0c;为了能…

语句数据库查询有数据,放在帆软预览没数据

问题描述&#xff1a; 要展示的数据&#xff0c;写的sql放在帆软里面预览没数据&#xff0c;然后将语句预览丢在数据库里执行有数据。 问题解决: 1. 首先你要确保两个用的是一个数据库&#xff0c;如果在生产环境中&#xff0c;一般是会有多个数据库&#xff0c;所以你要确保你…

Spring boot 发送文本邮件 和 html模板邮件

Spring boot 发送文本邮件 和 html模板邮件 提示&#xff1a;这里使用 spring-boot-starter-mail 发送文本邮件 和 html模板邮件 文章目录 Spring boot 发送文本邮件 和 html模板邮件一、开启QQ邮箱里的POP3/SMTP服务①&#xff1a;开启步骤 二、简单配置①&#xff1a;引入依赖…

「JavaSE」Lambda表达式

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;快来卷Java啦 &#x1f387;欢迎点赞收藏加关注哦&#xff01; Lambda表达式 &#x1f349;简介&#x1f349;函数式接口&#x1f34c;注解 &#x1f349;语法&#x1f349;Lambda表达式的基本…

如何使用Java语言发票查验接口实现发票真伪查验、票据ocr

随着时代潮流的发展&#xff0c;企业也在寻找更加便捷、高效的办公模式&#xff0c;尤其是针对财务工作人员而言&#xff0c;繁琐的发票录入、查验工作占据了财务人员的大部分时间。对此&#xff0c;翔云提供了发票识别接口、发票查验接口&#xff0c;那么企业应当如何将这些接…

第二证券|沪指震荡涨0.49%,石油、有色等板块拉升

29日早盘&#xff0c;沪指盘中强势上扬&#xff0c;深成指、创业板指小幅走低&#xff0c;科创50指数跌超1%。 到午间收盘&#xff0c;沪指涨0.49%报3025.56点&#xff0c;深成指跌0.22%&#xff0c;创业板指微跌0.07%&#xff0c;科创50指数跌1.34%&#xff1b;两市算计成交5…

SAMRTFORMS 转换PDF 发送邮件

最终成果&#xff1a; *&---------------------------------------------------------------------**& Report ZLC_FIND_EXIT*&---------------------------------------------------------------------**&根据T-CODE / 程序名查询出口、BADI增强*&-------…
最新文章