Doris删除数据工具

news/2024/7/7 20:55:00

文章目录

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

概要

对于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://lihuaxi.xjx100.cn/news/2131100.html

相关文章

智能数据建模软件DTEmpower 2024R1新版本功能介绍

DTEmpower是由天洑软件自主研发的一款通用的智能数据建模软件&#xff0c;致力于帮助工程师及工科专业背景学生&#xff0c;利用工业领域中的仿真、试验、测量等各类数据进行挖掘分析&#xff0c;建立高质量的数据模型&#xff0c;实现快速设计评估、实时仿真预测、系统参数预警…

3.亿级积分数据分库分表:ShardingSphere官方提供的平滑数据迁移方案介绍,有什么缺点呢?

前面的 2.亿级积分数据分库分表&#xff1a;增量数据同步之代码双写&#xff0c;为什么没用Canal&#xff1f; 博客中介绍了实现平滑数据迁移的两种方案&#xff1a;Canal监听MySQL的binlog、代码双写&#xff0c;也分别介绍了两种方案的实现原理及优缺点&#xff0c;最后基于…

【Node.js从基础到高级运用】十九、Node.js 捕获错误之“未捕获的异常”

引言 在 Node.js 应用程序中&#xff0c;错误处理是保证应用稳定性和可靠性的关键部分。特别是“未捕获的异常”&#xff08;uncaught exceptions&#xff09;&#xff0c;如果不妥善处理&#xff0c;很可能会导致整个进程崩溃。在本文中&#xff0c;我们将探讨如何在 Node.js …

Composer常见错误解决

Composer 是 PHP 社区广泛使用的一个依赖管理工具&#xff0c;它帮助开发者定义、管理和安装项目所需的库。在使用 Composer 的过程中&#xff0c;可能会遇到各种错误和问题。以下是一些常见的 Composer 错误及其解决方法&#xff1a; 1. 内存限制错误 错误信息&#xff1a;P…

|行业洞察·趋势报告|《2024旅游度假市场简析报告-17页》

报告的主要内容解读&#xff1a; 居民收入提高推动旅游业发展&#xff1a;报告指出&#xff0c;随着人均GDP的提升&#xff0c;居民的消费能力增强&#xff0c;旅游需求从传统的观光游向休闲、度假游转变&#xff0c;国内人均旅游消费持续增加。 政府政策促进旅游市场复苏&…

面试前端八股文十问十答第一期

面试前端八股文十问十答第一期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01;关注专栏后就能收到持续更新&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1&#xff09;http 和 https 的基本概念 H…

手把手写深度学习(25):下载并清洗WebVid-10M数据集

手把手写深度学习(0)&#xff1a;专栏文章导航 前言&#xff1a;WebVid-10M是一个大型文本-视频配对数据集&#xff0c;时至今日&#xff0c;依旧是做视频理解、视频生成等任务的首选数据集。这篇博客手把手详细教大家如何下载和清洗这个数据集。 目录 下载Meta CSV文件 下载…

江协科技STM32:按键控制LED光敏传感器控制蜂鸣器

按键控制LED LED模块 左上角PA0用上拉输入模式&#xff0c;如果此时引脚悬空&#xff0c;PA0就是高电平&#xff0c;这种方式下&#xff0c;按下按键&#xff0c;引脚为低电平&#xff0c;松下按键&#xff0c;引脚为高电平 右上角PA0&#xff0c;把上拉电阻想象成弹簧 当按键…