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

一、介绍

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; //判断是 参数 /Sqlprivate 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; //判断是 参数 /Sqlprivate 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.mzph.cn/news/850672.shtml

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

相关文章

python数据分析-ZET财务数据分析

一、公司背景 中兴通讯股份有限公司是一家总部位于中国深圳的跨国公司&#xff0c;致力于为全球客户提供通信设备和解决方案。公司成立于1985年&#xff0c;自成立以来一直致力于为客户提供创新的通信技术和服务。中兴通讯的业务涵盖多个领域&#xff0c;包括但不限于高端路由…

【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 可见…

idea打开hierarchy面板

hierarchy&#xff1a;查看类层级关系图 不同版本的IDEA的快捷键不一样&#xff0c;同时如果修改了IDEA快捷键&#xff0c;也可能会不一样&#xff0c;具体查看可通过IDEA上方的Navigate来查看navigate--Type Hierarchy&#xff0c;就可以看见其快捷键了&#xff0c;我的快捷键…

(四)React组件、useState

1. 组件 1.1 组件是什么 概念&#xff1a;一个组件就是用户界面的一部分&#xff0c;它可以有自己的逻辑和外观&#xff0c;组件之间可以相互嵌套&#xff0c;也可以复用多次。 组件化开发可以让开发者像搭积木一样构建一个完整的庞大应用 1.2 React组件 在React中&#xf…

less---20-28

less-20 这关登陆成功会显示cookie,所以抓包在cookie处注入 less-21 这关登陆成功会显示cookie,所以抓包在cookie处注入&#xff0c;发现不成功&#xff0c;查看代码发现被编码 先对注入语句进行base64编码再注入 less-22 闭合字符",同21关 less-23 这关查看代码发现…

Java现在还适合入门吗?

计算机技术在当今的社会&#xff0c;已经变得越来越热&#xff0c;充斥着我们生活的方方面面。人们的工作或是休闲&#xff0c;离不开互联网和电脑&#xff0c;这既受益于各类软件的诞生&#xff0c;也与时下的技术息息相关。Java作为编程界赫赫有名的语言&#xff0c;在最近几…

八爪鱼现金流-018,持续打磨

八爪鱼,被动收入,财务自由,现金流,现金流游戏,各银行利率,money,资产负债表,财务自由,资产管理,个人理财,管理个人资产,理财,打造被动收入,躺着赚钱,让钱为我打工

力扣2444.统计定界子数组的数目

力扣2444.统计定界子数组的数目 观察到不满足条件的数 可以作为天然的分割线 因此在枚举右端点的过程中 预处理minK&#xff0c;maxK和分割线上一次出现的下标 res min(min_i,max_i) - i0; 但是因为可能在到下个区段时 min_i和max_i尚未更新 导致结果为负数 所以要跟0再取一…

LabVIEW在高校中的应用

LabVIEW 作为一款功能强大的图形化编程工具&#xff0c;在高校中有广泛的应用。它不仅用于教学实验&#xff0c;还广泛应用于科研项目和工程训练。本文将从教学、科研、实验室管理和学生技能培养等多个角度&#xff0c;详细分析LabVIEW在高校中的应用。 教学应用 课程设计 自动…

完全二叉树的节点个数-力扣

完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层&#xff0c;则该层包含 1~ 2h 个节点。 因此&#xff0c;…

深入Llama2:掌握未来语言模型的秘密

Llama2是一个基于Transformer架构的大型语言模型&#xff0c;它旨在处理和理解大规模的文本数据。作为技术人员&#xff0c;了解Llama2的工作原理、模型结构和训练方法对于有效利用该模型至关重要。本文将详细介绍Llama2的基本概念、主要作用、使用方法及注意事项。 一、简介 …

多模态vlm综述:An Introduction to Vision-Language Modeling 论文解读

目录 1、基于对比学习的VLMs 1.1 CLIP 2、基于mask的VLMs 2.1 FLAVA 2.2 MaskVLM 2.3 关于VLM目标的信息理论视角 3、基于生成的VLM 3.1 学习文本生成器的例子: 3.2 多模态生成模型的示例: 3.3 使用生成的文本到图像模型进行下游视觉语言任务 4、 基于预训练主干网…

Python | C++ | MATLAB | Julia | R 市场流动性数学预期评估量

&#x1f3af;要点 &#x1f3af;市场流动性策略代码应用&#xff1a;&#x1f3af;动量策略&#xff1a;滚动窗口均值策略、简单移动平均线策略、指数加权移动平均线策略、相对强弱指数、移动平均线收敛散度交叉策略、三重指数平均策略、威廉姆斯 %R 策略 | &#x1f3af;均值…

LLVM Cpu0 新后端7 第二部分 窥孔优化

想好好熟悉一下llvm开发一个新后端都要干什么&#xff0c;于是参考了老师的系列文章&#xff1a; LLVM 后端实践笔记 代码在这里&#xff08;还没来得及准备&#xff0c;先用网盘暂存一下&#xff09;&#xff1a; 链接: https://pan.baidu.com/s/1yLAtXs9XwtyEzYSlDCSlqw?…

170.二叉树:平衡二叉树(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr, right(nullptr) {}* Tree…

第103天: 权限提升-Linux 系统辅助项目脏牛Dirty内核漏洞SUIDGUID

项目下载地址 综合类探针&#xff1a; https://github.com/liamg/traitor 自动化提权&#xff1a; https://github.com/AlessandroZ/BeRoot 信息收集&#xff1a; https://github.com/rebootuser/LinEnum https://github.com/sleventyeleven/linuxprivchecker 漏洞探针&#xf…

Webpack前端打包工具详解

目录 Webpack前端打包工具详解一、Webpack 的作用二、Webpack 的安装和基本使用1. 安装 Webpack2. 创建 Webpack 配置文件3. 运行 Webpack 三、Webpack 核心概念1. 入口&#xff08;Entry&#xff09;2. 输出&#xff08;Output&#xff09;3. 加载器&#xff08;Loaders&#…

【wiki知识库】06.文档管理页面的添加--前端Vue部分

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 一、&#x1f525;今日目标 二、&#x1f43b;前端Vue模块的改造 BUG修改 1.wangeditor无法展示问题 2.弹窗无法正常关闭问题 2.1 添加admin-doc.vue 2.1.1 点击admin-ebook中的路由跳转到admin-doc 2.2.2 进入…

Rust-06-所有权

所有权&#xff08;系统&#xff09;是 Rust 最为与众不同的特性&#xff0c;它让 Rust 无需垃圾回收即可保障内存安全&#xff0c;下面是所有权以及相关功能&#xff1a;借用&#xff08;borrowing&#xff09;、slice 以及 Rust 如何在内存中布局数据。 通过所有权系统管理内…

CSDN个人主页动态地图(前端/后端)

前段时间有人问我&#xff0c;关于CSDN个人主页动态地图的实现&#xff0c;我来解答一下。 这里要注意一下&#xff1a;使用CSDN的API需要遵循其开发者协议和使用规范&#xff0c;确保你的使用方式符合相关规定 前端部分&#xff1a; 创建一个HTML页面作为个人主页。在页面上放…