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();// 使用线程执行sqlSystem.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() {@Overridepublic 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.mzph.cn/news/777063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

王道c语言-二叉树前序、中序、后序、层次遍历

main.cpp #include "function.h"//abdhiejcfg 前序遍历深度优先遍历 abdhiejcfg void PreOrder(BiTree p) {if (p ! NULL) {printf("%c ", p->c);//等价于putchar(p->c);等价于visit函数伪代码PreOrder(p->lchild);PreOrder(p->rchild);} }//…

【数据结构】顺序表的实现——静态分配

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;数据结构 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

【微服务篇】深入理解微服务可观测性原理(Log,Metric,Trace)

可观测性 微服务的可观测性是指通过收集、分析和监控微服务架构中各个组件的数据来理解其行为和性能的能力。这对于确保系统的健康、响应性和安全至关重要。可观测性主要从日志&#xff08;Log&#xff09;、指标&#xff08;Metric&#xff09;和追踪&#xff08;Trace&#…

指针数组的有趣程序【C语言】

文章目录 指针数组的有趣程序指针数组是什么&#xff1f;指针数组的魅力指针数组的应用示例&#xff1a;命令行计算器有趣的颜色打印 结语 指针数组的有趣程序 在C语言的世界里&#xff0c;指针是一种强大的工具&#xff0c;它不仅能够指向变量&#xff0c;还能指向数组&#…

【Java程序设计】【C00344】基于Springboot的船舶维保管理系统(有论文)

基于Springboot的船舶维保管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 项目获取 &#x1f345;文末点击卡片获取源码&#x1f345; 开发环境 运行环境&#xff1a;推荐jdk1.8&#xff1b; 开发工具&#xff1a;eclipse以及i…

OpenCV图像二值化

1.二值图像 灰度图像 0 - 255二值图像 0&#xff08;黑&#xff09; / 255&#xff08;白&#xff09; 2.二值分割 五种阈值分割方法&#xff08;阈值T&#xff09;&#xff1a; 大于T为255&#xff0c;小于T为0 大于T为0&#xff0c;小于T为255 小于T为原值 else T 小于…

直面位运算

在这篇文章之前&#xff0c;笔者只是简单了解过位运算相关概念&#xff0c;但是每次刷LeetCode碰到位运算相关题目&#xff0c;都会敬而远之。一方面是觉得看起来晦涩难懂&#xff0c;另一方面觉得日常开发用处不大。 近期本着学习的目的&#xff0c;静下心来研究了一下&#x…

自己如何利用简单的代码,生成一个小游戏

原文&#xff1a;dlshuhua.com/post/79125.html 要生成一个小游戏&#xff0c;我们可以使用许多不同的编程语言和框架。这里&#xff0c;我将给出一个使用Python和其内置库tkinter创建简单猜数字游戏的例子。这个游戏的工作原理是&#xff1a;程序随机生成一个1到100之间的数字…

单链表的插入和删除

一、插入操作 按位序插入&#xff08;带头结点&#xff09;&#xff1a; ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。 typedef struct LNode{ElemType data;struct LNode *next; }LNode,*LinkList;//在第i 个位置插插入元素e (带头结点) bool Li…

国内IP切换软件:解锁网络世界的新钥匙

在数字化快速发展的今天&#xff0c;互联网已成为我们生活中不可或缺的一部分。然而&#xff0c;伴随着网络使用的深入&#xff0c;许多用户逐渐意识到&#xff0c;不同的IP地址可能会带来截然不同的网络体验。为了应对这一问题&#xff0c;国内IP切换软件应运而生&#xff0c;…

Rust引用借用 vs 原始指针

let v: i32 10; let v1 &v; let a: *const i32 &v; println!("a{:p}", a); let b a as *mut i32; //无法从&v直接转换成*mut i32&#xff0c;需要从*const i32过度 println!("b{:p}", b); unsafe {*b1; } println!("v{} v1{}"…

c++部分题

const关键字与宏定义的区别是什么&#xff1f; const关键字和宏定义在功能上有相似之处&#xff0c;但在实现和使用上有很大的区别。 作用域和类型安全性&#xff1a; const关键字定义的常量具有作用域和类型安全性。它们的作用域仅限于声明它们的块&#xff0c;并且在编译时会…

iOS客户端自动化UI自动化airtest+appium从0到1搭建macos+脚本设计demo演示+全网最全最详细保姆级有步骤有图

Android客户端自动化UI自动化airtest从0到1搭建macos脚本设计demo演示全网最全最详细保姆级有步骤有图-CSDN博客 避坑系列-必读&#xff1a; 不要安装iOS-Tagent &#xff0c;安装appium -这2个性质其实是差不多的都是为了安装wda。注意安装appium最新版本&#xff0c;安装完…

结构体,联合体,枚举( 1 )

目录 前言 1.结构体 1.1结构体的声明 1.2结构体变量的创建和初始化 1.3结构体成员的访问字符 1.4结构体的内存大小 1.4.1对齐规则 1.5结构体传参 前言 在编程的世界里&#xff0c;数据结构的选择对于程序的效率和可读性有着至关重要的影响。不同的数据结构适用于不同的…

19. 变量

文章目录 一、变量二、变量的定义格式 一、变量 变量&#xff1a;程序中临时存储数据的容器&#xff0c;在程序执行过程中&#xff0c;其值有可能发生改变的量&#xff08;数据&#xff09;。但是这个容器中只能存一个值。 应用场景&#xff1a;在我们登录页面的时候&#xf…

2024最新华为OD机试试题库全 -【符号运算】- C卷

1. 🌈题目详情 1.1 ⚠️题目 给定一个表达式,求其分数计算结果。 表达式的限制如下: 所有的输入数字皆为正整数(包括0)仅支持四则运算(*/)和括号结果为整数或分数,分数必须化为最简格式(比如6,3/4,7/8,90/7)除数可能为0,如果遇到这种情况,直接输出"ERR…

C++多重继承与虚继承

多重继承的原理 多重继承(multiple inheritance)是指从多个直接基类中产生派生类的能力。 多重继承的派生类继承了所有父类的属性。 在面向对象的编程中&#xff0c;多重继承意味着一个类可以从多个父类继承属性和方法。 就像你有一杯混合果汁&#xff0c;它是由多种水果榨取…

Spring Boot(一)— Maven

Maven是一个跨平台的项目管理工具&#xff0c;主要服务于基于Java平台的项目构建、依赖管理和项目信息管理。通过其项目对象模型&#xff08;POM&#xff09;&#xff0c;可以自动下载和管理项目所需的库和插件。 1 Maven 以上的pom.xml 包含了在开发中常用的标签与功能。 &…

KY7 质因数的个数(用Java实现)

描述 求正整数N(N>1)的质因数的个数。 相同的质因数需要重复计算。如1202*2*2*3*5&#xff0c;共有5个质因数。 输入描述&#xff1a; 可能有多组测试数据&#xff0c;每组测试数据的输入是一个正整数N&#xff0c;(1<N<10^9)。 输出描述&#xff1a; 对于每组数…

46.continue语句

目录 一.continue语句 二.视频教程 一.continue语句 continue语句的作用和break语句很像&#xff0c;break语句会跳出当前循环&#xff0c;而continue语句则是跳出本次循环&#xff0c;继续执行下一次循环。 举个例子&#xff1a; #include <stdio.h>void main(void)…