面试:25Wqps高吞吐写Mysql,100W数据4秒写完,如何实现?

news2024/11/26 16:37:09

25Wqps是什么概念?

QPS(Queries Per Second):是衡量信息检索系统(例如搜索引擎或数据库)在一秒钟内接收到的搜索流量的一种常见度量。

通过概念我们能很清楚知道 QPS = 并发数/响应时间,即100W/4s = 25Wqps

相关方法

当高并发插入大量数据的时候就需要用到批处理这个Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下,批量处理 比单独提交处理更有效率

用得到的核心方法:

  • addBatch(String):添加需要批量处理的SQL语句或是参数;

  • executeBatch():执行批量处理语句;

  • clearBatch():清空缓存的数据

方式一:直接插入

普通插入100w数据

@Test
public void Test1() {
    long start = System.currentTimeMillis();//开始计时【单位:毫秒】
    Connection conn = jdbcUtils.getConnection();//获取数据库连接
    String sql = "insert into a(id, name) VALUES (?,null)";
    PreparedStatement ps = null;
    try {
        ps = conn.prepareStatement(sql);
        for (int i = 1; i <= 1000000; i++) {
            ps.setObject(1, i);//填充sql语句种得占位符
            ps.execute();//执行sql语句
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        jdbcUtils.close(conn, ps, null);
    }
    //打印耗时【单位:毫秒】
    System.out.println("百万条数据插入用时:" + (System.currentTimeMillis() - start)+"【单位:毫秒】");
}

用时:3736/60= 62分钟多 

方式二:使用批处理

使用PreparedStatement

@Test
public void Test2() {
    long start = System.currentTimeMillis();
    Connection conn = jdbcUtils.getConnection();//获取数据库连接
    String sql = "insert into a(id, name) VALUES (?,null)";
    PreparedStatement ps = null;
    try {
        ps = conn.prepareStatement(sql);
        for (int i = 1; i <= 1000000; i++) {
            ps.setObject(1, i);
            ps.addBatch();//将sql语句打包到一个容器中
            if (i % 500 == 0) {
                ps.executeBatch();//将容器中的sql语句提交
                ps.clearBatch();//清空容器,为下一次打包做准备
            }
        }
        //为防止有sql语句漏提交【如i结束时%500!=0的情况】,需再次提交sql语句
        ps.executeBatch();//将容器中的sql语句提交
        ps.clearBatch();//清空容器
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        jdbcUtils.close(conn, ps, null);
    }
    System.out.println("百万条数据插入用时:" + (System.currentTimeMillis() - start)+"【单位:毫秒】");
}

用时:3685/60= 61分钟多

这时候你会发现不是说批处理会快很多吗,为什么实际上没有变化?

而这实际上是因为没有开启重写批处理语句

优化一:

在方式二的基础上, 允许jdbc驱动重写批量提交语句,在数据源的url需加上 &rewriteBatchedStatements=true ,表示(重写批处理语句=是) 

spring.datasource.url = jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&rewriteBatchedStatements=true
spring.datasource.username = root
spring.datasource.password = 123456

用时:10031/60 = 10s

优化二:

在方式三的基础上,取消自动提交sql语句,当sql语句都提交了才手动提交sql语句

conn.setAutoCommit(false)(设置自动提交=否)

@Test
public void Test3() {
    long start = System.currentTimeMillis();
    Connection conn = jdbcUtils.getConnection();//获取数据库连接
    String sql = "insert into a(id, name) VALUES (?,null)";
    PreparedStatement ps = null;
    try {
        ps = conn.prepareStatement(sql);
        conn.setAutoCommit(false);//取消自动提交
        for (int i = 1; i <= 1000000; i++) {
            ps.setObject(1, i);
            ps.addBatch();
            if (i % 500 == 0) {
                ps.executeBatch();
                ps.clearBatch();
            }
        }
        ps.executeBatch();
        ps.clearBatch();
        conn.commit();//所有语句都执行完毕后才手动提交sql语句
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        jdbcUtils.close(conn, ps, null);
    }
    System.out.println("百万条数据插入用时:" + (System.currentTimeMillis() - start)+"【单位:毫秒】");
}

用时:4秒左右

具体实现步骤:

  1. 获取数据库连接。

  2. 创建 Statement 对象。

  3. 定义 SQL 语句,使用 PreparedStatement 对象预编译 SQL 语句并设置参数。

  4. 取消自动提交

  5. 将sql语句打包到一个Batch容器中,  添加需要批量处理的SQL语句或是参数

  6. 执行批处理操作。

  7. 清空Batch容器,为下一次打包做准备

  8. 不断迭代第5-7步,直到数据处理完成。

  9. 关闭 Statement 和 Connection 对象。

注意事项:

  • 使用setAutoCommit(false) 来禁止自动提交事务,然后在每次批量插入之后手动提交事务
  • 批量提交数据的时候url要设置rewriteBatchedStatements=true
  • sql语句不能有分号否则抛出BatchUpdateException异常

  • 设置适当的批处理大小:批处理大小指在一次插入操作中插入多少行数据。如果批处理大小太小,插入操作的频率将很高,而如果批处理大小太大,可能会导致内存占用过高。通常,建议将批处理大小设置为1000-5000行,这将减少插入操作的频率并降低内存占用

  • 采用适当的等待时间:等待时间指在批处理操作之间等待的时间量。等待时间过短可能会导致内存占用过高,而等待时间过长则可能会延迟插入操作的速度。通常,建议将等待时间设置为几秒钟到几十秒钟之间,这将使操作变得平滑且避免出现内存占用过高等问题。

参考文章:网易一面:25Wqps高吞吐写Mysql,100W数据4秒写完,如何实现?

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

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

相关文章

conda创建python虚拟环境

1.查看当前存在那些虚拟环境 conda env list conda info -e 2.conda安装虚拟环境 conda create -n my_env_name python3.6 2.1在anaconda下改变python版本 当前3.7 安装3.7 conda create -n py37 python3.7 conda activate py37 conda create -n py37 python3.7conda a…

多通道振弦数据记录仪应用于大坝岩土工程监测

多通道振弦数据记录仪应用于大坝岩土工程监测 随着现代科技的不断发展&#xff0c;多通道振弦数据记录仪的应用越来越广泛&#xff0c;其中在大坝岩土工程监测中的应用也越来越普遍。多通道振弦数据记录仪通过采集振动信号的信息&#xff0c;可以有效地监测大坝的安全性和稳定…

【校招VIP】数据库理论之存储过程

考点介绍&#xff1a; 存储过程可以说是一个记录集&#xff0c;它是由一些T-SQL语句组成的代码块&#xff0c;这些T-SQL语句代码像一个方法一样实现一些功能&#xff08;对单表或多表的增删改查&#xff09;&#xff0c;然后再给这个代码块取一个名字&#xff0c;在用到这个功能…

给数组中多次出现的数据添加不同的标记

/*** params 取数组中第二次出现的元素之后的数据* returns*/ export const getElementsAfterSecondOccurrence (arr, column, targetValue) > {let count 0;let secondIndex -1;for (let i 0; i < arr.length; i) {if (arr[i][column] targetValue) {count;if (co…

VmWare安装CentOs8

文章目录 创建虚拟机1、创建虚拟机2、选择虚拟机硬件兼容性3、安装客户机操作系统4、安装客户机操作系统5、命名虚拟机6、处理器配置7、分配虚拟机的内存8、配置网络类型9、选择I/O控制器类型10、选择磁盘类型11、选择磁盘12、指定磁盘容量13、指定磁盘文件14、完成创建 2.安装…

STM32的HAL库的定时器使用

用HAL库老是忘记了定时器中断怎么配置&#xff0c;该调用哪个回调函数。今天记录一下&#xff0c;下次再忘了就来翻一下。 系统的时钟配置&#xff0c;定时器的时钟是84MHz 这里定时器时钟是84M&#xff0c;分频是8400后&#xff0c;时基就是1/10000s&#xff0c;即0.1ms。Per…

百度文心一言GPT免费入口也来了!!!

文心一言入口地址&#xff1a;https://cloud.baidu.com/wenxin.html?daohang

【校招VIP】前端校招考点之UDP

考点介绍&#xff1a; UDP是非面向连接协议&#xff0c;使用udp协议通讯并不需要建立连接&#xff0c;它只负责把数据尽可能发送出去&#xff0c;并不可靠&#xff0c;在接收端&#xff0c;UDP把每个消息断放入队列中&#xff0c;接收端程序从队列中读取数据。 『前端校招考点…

华为云 sfs 服务浅谈

以root用户登录弹性云服务器。 以root用户登录弹性云服务器。 安装NFS客户端。 查看系统是否安装NFS软件包。 CentOS、Red Hat、Oracle Enterprise Linux、SUSE、Euler OS、Fedora或OpenSUSE系统下&#xff0c;执行如下命令&#xff1a; rpm -qa|grep nfs Debian或Ubuntu系统下…

微信小程序 校园周边美食商城分享系统

管理员、会员、商家可通过Android系统手机打开系统&#xff0c;注册登录后可进行管理员后端&#xff1b;首页、个人中心、会员管理、商家管理、美食类型管理、美食信息管理、美食交流、我的收藏管理、系统管理、订单管理&#xff0c;会员前端&#xff1b;首页、美食信息、美食交…

PHP8的箭头函数-PHP8知识详解

php 7.4 引入了箭头函数&#xff08;Arrow Functions&#xff09;&#xff0c;并在 PHP 8 中得到了进一步改进和扩展。 箭头函数是一种更简洁的匿名函数形式&#xff0c;它们提供了一种更便捷的方式来定义轻量级的、单行的回调函数。 箭头函数的语法如下&#xff1a; fn (参…

我的创作纪念日----探索创作之旅

创作之旅 创作之始启程追寻&#xff1a;寻觅灵感的起点思绪迸发&#xff1a;创意萌芽与滋长 创作之途探索未知&#xff1a;友人的帮助与指导 创作之行倾听内心&#xff1a;创意荒漠的探寻 主页传送门&#xff1a;&#x1f4c0; 传送 创作之始 ​ ​  在我尚未察觉的瞬间&…

【校招VIP】java专业课之三次握手四次挥手

考点介绍&#xff1a; 三次握手四次挥手问题是校招面试中的必考题。 三次握手即TCP连接的建立。这个连接必须是一方主动打开&#xff0c;另一方被动打开的。四次挥手即TCP连接的释放(解除)。连接的释放必须是一方主动释放&#xff0c;另一方被动释放。 『java专业课之三次握手…

JPA在不写sql的情况下实现模糊查询

本文已收录于专栏 《Java》 目录 背景介绍概念说明单字段模糊匹配&#xff1a;多字段模糊匹配&#xff1a; 实现过程代码实现1.写一个实体类去实现Specification接口&#xff0c;重写toPredicate方法2.定义一个接口去继承JpaRepository接口&#xff0c;并指定返回的类型和参数类…

YOLOv5训练后利用权重对特征图可视化

我们可以可视化某层的特征图添加到论文中&#xff0c;属于锦上添花了&#xff01; 小小的技巧&#xff0c;有需要的同学可以自取代码尝试一下。 python detect.py --weights best.pt --imgsz 640 --source ./data/image/ --visualize运行过程中&#xff1a; 运行后即可生成特…

大数据学习:haproxy实现impala的负载均衡

HAProxy实现Impala的负载均衡 1.HAProxy安装及启停 1.1 在集群中选择一个节点&#xff0c;使用yum方式安装HAProxy服务 [rootdata01-dev ~]# yum -y install haproxy1.2 启动与停止HAProxy服务&#xff0c;并将服务添加到自启动列表 [rootdata01-dev ~]# service haproxy s…

Redis持久化——RDF与AOF两种方式怎么做?有什么区别?

目录 1. 什么是RDB 2. save 和 bgsave 命令主动保存数据 2.1 save 2.2 bgsave 3. Redis 内部自动RDB机制 4. RDB 底层是如何实现 bgsave 的&#xff1f; 5. RDB 的缺点 6. 什么是AOF&#xff1f; 7. AOF文件的缺点&#xff1f; 8. AOF 重写文件配置 9. RDB 与 AOF …

Unexpected mutation of “xxxx“ prop

原因 是因为子级修改了父级的数据&#xff0c;所以eslint执行的时候报了这个错 修复方式 1 如果是弹窗等组件&#xff0c;可以根据功能进行修改&#xff0c;比如我这块用的 element ui 的 dialog&#xff0c;便可以改成这样 使用 model-value 代替 修复方式 2 新建子组件…

CTFhub-文件上传-MIME绕过

用哥斯拉生成 php 木马文件 1.php 抓包---> 修改 conten-type 类型 为 imge/jpeg 用蚁剑连接 ctfhub{8e6af8109ca15932bad4747a}

云计算的三个主要服务模型:IaaS、PaaS 和 SaaS

文章目录 介绍基础设施即服务&#xff08;Infrastructure as a Service&#xff0c;IaaS&#xff09;平台即服务&#xff08;Platform as a Service&#xff0c;PaaS&#xff09;软件即服务&#xff08;Software as a Service&#xff0c;SaaS&#xff09; 区别基础设施即服务&…