clickHouse实现表自增ID的代码及相关逻辑

news2024/10/7 15:03:09

一、介绍

clickHourse表自增ID主要时两种方式:

  • insert数据时,手动维护一个全局ID
  • 给表设置uuid字段,使用 generateUUIDv4()函数赋予默认值。

这里的话推荐手动维护一个全局的自增ID,不推荐使用UUID的方式,主要原因有以下几个:

  • uuid字段占用的存储空间比手动维护自增ID的空间大很多,可参数性能对比章节。
  • 使用uuid字段,如果该表涉及到按批次分别读取,UUID无法实现因为UUID不能用来比较。
  • 如果使用需要做分页,UUID如何设置偏移量这是一个问题。

二、手动维护表的全局自增ID(推荐)

代码思路

  • 在插入数据之前,可以为每条记录生成一个唯一的自增ID,并将其作为排序的依据。
  • 多线程入库的话使用 Java的同步机制来确保ID的唯一性即AtomicLong类
  • 程序提供时或者插入前查询最大该表最大的ID:在插入新数据之前,从表中查询当前的最大ID。这个最大ID将作为新数据插入时的起始ID。
  • 然后每一次insert给DATAID赋予 AtomicLong类的值+1 即可

表结构

CREATE TABLE default.SQLLOG_FULL20240609_1809
(
    `DATAID` UInt64,
    `LOGTIME` DateTime64(3,'Asia/Shanghai'),
    `CURRTIME` DateTime('Asia/Shanghai') DEFAULT now(),
    `SESS` String,
    `THRD` Int64,
    `USERNAME` String,
    `TRXID` Int64,
    `STMT` String,
    `APPNAME` String,
    `IP` String,
    `INFOSTR` String
)
ENGINE = MergeTree
PARTITION BY toHour(LOGTIME)
ORDER BY (DATAID,LOGTIME)
SETTINGS index_granularity = 8192;

批量插入代码

@Data
public class LineBean
{
	public static int SQL_TYPE_PARAMS = 1;
	public static int SQL_TYPE_SQLSTR = 2;
	private String time;
	private String sess;
	private String thrd;
	private String user;
	private String trxid;
	private String stmt;
	private String appname;
	private String ip;
	private String infoStr;
	private Integer lineType; //判断是 参数 /Sql
	private String lineExecSqlType;
}

public class ClickHouseDbConnection {

    public static AtomicLong idGenerator = new AtomicLong(0);

    public static void main(String[] args) {
        //1. 设置当前表的最大ID 并放置到    
       Long tableMaxId = querySqlLogTableMaxId(connection, dbSqllogTableName);
        idGenerator.set(tableMaxId+1);
        //2. 封装对象List
        //3. 执行batchDataListCommit方法
        
    }
    
    
    //获取表中的DATAID最大值
    private static Long querySqlLogTableMaxId() throws SQLException {
        String url = "jdbc:clickhouse://192.168.112.146:8123/default";
        Properties properties = new Properties();
        properties.setProperty("user", "default");
        properties.setProperty("password", "root");
        
        Connection connection = DriverManager.getConnection(url, properties);
        String querySql = "SELECT MAX(DATAID) AS DATAID FROM "+dbSqllogTableName;
        ResultSet resultSet = connection.prepareStatement(querySql).executeQuery();
        resultSet.next();
        return resultSet.getLong(1);
    }

    

    public static void batchDataListCommit(List<LineBean>  batchData) {
        
        
        
        
          
        String url = "jdbc:clickhouse://192.168.112.146:8123/default";
        Properties properties = new Properties();
        properties.setProperty("user", "default");
        properties.setProperty("password", "root");
            
        String sqlLogTableName = PropertiesUtils.getCustomPropertyValue(CommonConstant.DBMS_SYNC_TABLE_NAME);
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = DriverManager.getConnection(url, properties);
            String insert_sql = "insert into "+sqlLogTableName+"(LOGTIME, SESS, THRD, USERNAME, TRXID, STMT, APPNAME, IP, INFOSTR) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
        
            connection.setAutoCommit(true);//将自动提交关闭
            preparedStatement = connection.prepareStatement(insert_sql);
        
            for (int i = 0; i < batchData.size(); i++) {
                int idx = 1;
                LineBean lineBean = batchData.get(i);
                preparedStatement.setLong(idx++, idGenerator.incrementAndGet());
                preparedStatement.setTimestamp(idx++,  new Timestamp(DateUtil.parse(lineBean.getTime(),DateTimeUtils.FORMATTER_STR).getTime()));
                preparedStatement.setString(idx++, lineBean.getSess());
                preparedStatement.setLong(idx++, Long.parseLong(lineBean.getThrd()));
                preparedStatement.setString(idx++, lineBean.getUser());
                preparedStatement.setLong(idx++, Long.parseLong(lineBean.getTrxid()));
                preparedStatement.setString(idx++, lineBean.getStmt());
                preparedStatement.setString(idx++, lineBean.getAppname());
                preparedStatement.setString(idx++, lineBean.getIp());
                preparedStatement.setString(idx++, lineBean.getInfoStr());
        
                preparedStatement.addBatch();
        
            }
            preparedStatement.executeBatch();
        
        } catch (SQLException e) {
            StaticLog.error(e,"batch dataList error info {}",e.getMessage());
        }finally {
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    StaticLog.error(e,"close db preparedStatement error info {}",e.getMessage());
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    StaticLog.error(e,"close db connection error info {}",e.getMessage());
                }
            }
        
        }
    }       
}

三、给表设置自增UUID字段

create table时 新增字段``DATAID UUID DEFAULT generateUUIDv4() 会默认生成唯一键
image.png

表结构

CREATE TABLE default.SQLLOG_FULL20240609_1220
(
  `DATAID` UUID DEFAULT generateUUIDv4(),
  `LOGTIME` DateTime64(3,'Asia/Shanghai'),
  `CURRTIME` DateTime('Asia/Shanghai') DEFAULT now(),
  `SESS` String,
  `THRD` Int64,
  `USERNAME` String,
  `TRXID` Int64,
  `STMT` String,
  `APPNAME` String,
  `IP` String,
  `INFOSTR` String
)
ENGINE = MergeTree
PARTITION BY toHour(LOGTIME)
ORDER BY (LOGTIME, CURRTIME)
SETTINGS index_granularity = 8192;

批量插入代码

@Data
public class LineBean
{
	public static int SQL_TYPE_PARAMS = 1;
	public static int SQL_TYPE_SQLSTR = 2;
	private String time;
	private String sess;
	private String thrd;
	private String user;
	private String trxid;
	private String stmt;
	private String appname;
	private String ip;
	private String infoStr;
	private Integer lineType; //判断是 参数 /Sql
	private String lineExecSqlType;
}



  public static void batchDataListCommit(List<LineBean>  batchData) {

    String url = "jdbc:clickhouse://192.168.112.146:8123/default";
    Properties properties = new Properties();
    properties.setProperty("user", "default");
    properties.setProperty("password", "root");
        
    String sqlLogTableName = PropertiesUtils.getCustomPropertyValue(CommonConstant.DBMS_SYNC_TABLE_NAME);
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    try {
        connection = DriverManager.getConnection(url, properties);
        String insert_sql = "insert into "+sqlLogTableName+"(LOGTIME, SESS, THRD, USERNAME, TRXID, STMT, APPNAME, IP, INFOSTR) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";

        connection.setAutoCommit(true);//将自动提交关闭
        preparedStatement = connection.prepareStatement(insert_sql);

        for (int i = 0; i < batchData.size(); i++) {
            int idx = 1;
            LineBean lineBean = batchData.get(i);

            preparedStatement.setTimestamp(idx++,  new Timestamp(DateUtil.parse(lineBean.getTime(),DateTimeUtils.FORMATTER_STR).getTime()));
            preparedStatement.setString(idx++, lineBean.getSess());
            preparedStatement.setLong(idx++, Long.parseLong(lineBean.getThrd()));
            preparedStatement.setString(idx++, lineBean.getUser());
            preparedStatement.setLong(idx++, Long.parseLong(lineBean.getTrxid()));
            preparedStatement.setString(idx++, lineBean.getStmt());
            preparedStatement.setString(idx++, lineBean.getAppname());
            preparedStatement.setString(idx++, lineBean.getIp());
            preparedStatement.setString(idx++, lineBean.getInfoStr());

            preparedStatement.addBatch();

        }
        preparedStatement.executeBatch();

    } catch (SQLException e) {
        StaticLog.error(e,"batch dataList error info {}",e.getMessage());
    }finally {
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                StaticLog.error(e,"close db preparedStatement error info {}",e.getMessage());
            }
        }
        if(connection!=null){
            try {
                connection.close();
            } catch (SQLException e) {
                StaticLog.error(e,"close db connection error info {}",e.getMessage());
            }
        }

    }
}       

四、关于表自增方式的性能对比

插入性能上差距不上,使用相同的1G日志进行批量入库
1)不添加自增ID,入库效率稳定在17S左右,表大小118M
2)使用UUID方式的自增ID方式,入库效率在17-21S左右,表大小为153M ,较不添加增长35M
3)使用外部维护表自增ID方式,入库效率在18S左右,表大小127M,较无主键时增长9M
image.png
image.png
image.png

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

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

相关文章

java —— 线程(一)

一、进程与线程 一个进程可以包含一个以上的线程&#xff0c;CPU 时间片切换的基本单位是线程。 二、创建线程 &#xff08;一&#xff09;继承 Thread 类 public class Task extends Thread{Override //重写run方法public void run(){System.out.pr…

Nginx部署多web进程

1、nginx介绍 Nginx是一个高性能的、开源的、跨平台的Web服务器和反向代理服务器。它是由俄罗斯的程序员Igor Sysoev开发的&#xff0c;并于2004年首次公开发布。 Nginx的特点包括&#xff1a; 高性能&#xff1a;Nginx使用事件驱动的架构&#xff0c;能够处理大量的并发连接…

HarmonyOS鸿蒙应用开发——ArkUI组件封装最佳实践

文章目录 背景与案例描述静态注册属性-封装UI组件动态注册属性-封装UI组件总结 背景与案例描述 在应用开发中&#xff0c;对一些频繁使用的业务UI组件常常会进行一层封装&#xff0c;提取到公共基础库中实现组件的复用&#xff0c;避免类似的逻辑重复编写&#xff0c;减少代码…

【前端技术】 ES6 介绍及常用语法说明

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

LabVIEW缝缺陷图像标注库

LabVIEW缝缺陷图像标注库 开发了一个基于LabVIEW平台构建的船舶焊缝缺陷图像标注库。该库旨在通过高效和简洁的方式处理和标注船舶焊缝缺陷图像&#xff0c;提高缺陷识别的准确性和效率&#xff0c;进而保障船舶的结构安全。 项目背景 在船舶制造过程中&#xff0c;焊接质量…

递归【1】(全排列andN皇后)(排列型回溯)

全排列 分治与递归 递归是实现分治的一种方法 思想思路 题目&#xff1a; 全排列i 我这样直接输出会多输出一个空行&#xff08;最后一个\n&#xff09; #include<stdio.h>using namespace std; const int maxn10; int an[maxn]; int n; bool hash[maxn]{0}; int c0…

STM32-15-DMA

STM32-01-认识单片机 STM32-02-基础知识 STM32-03-HAL库 STM32-04-时钟树 STM32-05-SYSTEM文件夹 STM32-06-GPIO STM32-07-外部中断 STM32-08-串口 STM32-09-IWDG和WWDG STM32-10-定时器 STM32-11-电容触摸按键 STM32-12-OLED模块 STM32-13-MPU STM32-14-FSMC_LCD 文章目录 STM…

【Java面试】十七、并发篇(上)

文章目录 1、synchronized关键字的底层原理&#xff1a;Monitor2、synchronized相关2.1 为什么说synchronized是重量级锁2.2 synchronized锁升级之偏向锁2.3 synchronized锁升级之轻量级锁 3、Java内存模型JMM4、CAS4.1 CAS流程4.2 CAS底层实现 5、volatile关键字的理解5.1 可见…

区块链(Blockchain)调查研究(一)

文章目录 1. 区块链是什么&#xff1f;2. 区块链分类和特点3. 区块链核心关键技术3.1 共识机制3.2 密码学技术3.4 分布式存储3.5 智能合约 4. 区块链未来发展趋势5. 区块链能做什么、不能做什么&#xff1f;5.1 第一部分5.2 第二部分5.3 第三部分&#xff08;结论&#xff09; …

八爪鱼现金流-019-个人对接支付,个人网站支付解决方案

背景&#xff1a; 随着用户量不断增加&#xff0c;服务器成本越来越大。想着实现会员制回点服务器成本。 业务场景分析&#xff1a; 用户在站点上付款 -----> 我监听到付款金额 -----> 给用户开通会员 调研&#xff1a; 支付宝和微信官方支付接口&#xff1a;基本都需…

MOS管十大品牌

MOS管十大品牌-场效应管品牌排行-MOS管品牌-Maigoo品牌榜

统计学研硕大数据统计练手11

统计学论文练手作业 题目AI绘图仅供欣赏 题目 2024年的《政府工作报告》中提出“深化大数据、人工智能等研发应用,开展“人工智能+”行动,打造具有国际竞争力的数字产业集群”,请同学们结合自己工作的所在行业或领域谈一谈大数据技术在人工智能时代下的应用现状、存在的问…

VSC++: 民意调查比例法

void 民意调查比例法() {//缘由https://bbs.csdn.net/topics/396521294?page1#post-411408461从题目描述看&#xff1a;902/3~300.7&#xff0c;1498/5~299.6也就是大约求2个数的公约数&#xff0c;并使得这个公约数尽量求出最小误差&#xff1f;且商小于某值。int a 0, aa …

JS(JavaScript)的引用方式介绍与代码演示

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

Mamba v2诞生:3 SMA与Mamba-2

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提…

从品牌的角度看老字号五芳斋如何“粽”出年轻味?

端午划着龙舟的浆又来到了我们身边&#xff0c;咸鸭蛋和粽子已经裹上精美的包装在货架上等待着它们的“有缘人”&#xff0c;其实长期以来&#xff0c;说起吃粽子除了“甜咸口”的辩论赛&#xff0c;貌似在产品上却并没有太多的创新&#xff0c;但近几年随着消费市场的不断创新…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 6月9日,星期日

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年6月9日 星期日 农历五月初四 1、 人社部&#xff1a;个人养老金开户人数已超6000万&#xff0c;其中31岁至40岁的中高收入人群是开户、缴费和购买产品的主力军。 2、 医保局刊文&#xff1a;研究显示集采仿制药替代原研药…

网关API(SpringCloudGateway)如何自定义Filter

1.前言 SpringCloud 虽然给我们提供了很多过滤器&#xff0c;但是这些过滤器功能都是固定的&#xff0c;无法满足用户的各式各样的需求。因此SpringCloud提供了过滤器的扩展功能自定过滤器。 开发者可以根据自己的业务需求自定义过滤器。 2. 自定义 GatewayFilter(局部过滤器)…

LangChain4j实战

基础 LangChain4j模型适配: Provider Native Image Sync Completion Streaming Completion Embedding Image Generation Scoring Function Calling OpenAI ✅ ✅ ✅ ✅ ✅ ✅ Azure OpenAI ✅ ✅ ✅ ✅ ✅ Hugging Face ✅ ✅ Amazon Bedrock ✅ ✅…

STM32中ADC在cubemx基础配置界面介绍

ADCx的引脚,对应的不同I/O口&#xff0c;可以复用。 Temperature :温度传感器通道。 Vrefint :内部参照电压。 Conversion Trigger: 转换触发器。 IN0 至 IN15,是1ADC1的16个外部通道。本示例中输出连接的是ADC2的IN5通道&#xff0c;所以只勾选IN5.Temperature Sensor Cha…