【开源项目】震惊JDBC查询比MyBatis查询慢

news2024/11/20 6:22:37

震惊JDBC查询比MyBatis查询快?

文章编写起始原因,在编写项目的时候碰到一个深坑,JDBC获取5000条数据,居然耗时261s,MyBatis同样的操作,耗时12s左右,震惊。看到这里下巴都快掉下来了。不是网上都说MyBatis就是封装了的JDBC吗?不是都说JDBC比MyBatis快很多很多吗?为啥这里却别这么大?

先上图,看看查询的具体情况吧
请添加图片描述

具体的代码如下:

private List<String> selectTransferData() {
    List<String> list = new ArrayList<>();
    ResultSet rs;
    Statement stmt;
    Connection newConn;
    try {
        newConn = druidDataSource.getConnection();
        stmt = newConn.createStatement();
        stmt.setFetchSize(Integer.MIN_VALUE);
        rs = stmt.executeQuery(sql);
    } catch (SQLException e) {
        logger.error("traceId: {}, mysql executeQuery error!!! error msg: {}", traceId, e.getMessage());
        throw new DataMigrationException(DataMigrationConstant.MYSQL_EXECUTE_QUERY_ERROR);
    }
    String[] cloumnSplit = transferInsertConfig.getTableCloumnName().split(",");
    try {
        while (rs.next()) {
            StringBuilder data = new StringBuilder("(");
            for (int i = 0; i < cloumnSplit.length; i++) {
                String cloumnName = cloumnSplit[i].replaceAll(" ", "");
                String string = rs.getString(cloumnName);
                data.append(string).append(", ");
            }
            String dataStr = data.substring(0, data.length() - 2) + ")\r\n";
            list.add(dataStr);
        }
    } catch (Exception e) {
        logger.error("traceId: {}, 获取查询结果集异常!!! error msg: {}", traceId, e.getMessage());
        throw new DataMigrationException("获取查询结果集异常, 异常信息:" + e.getMessage());
    } finally {
        try {
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
            if (newConn != null) {
                newConn.close();
            }
        } catch (Exception e) {
            logger.error("traceId: {}, close io error!!! error msg: {}", traceId, e.getMessage());
        }
    }
    return list;
}

代码里面执行的SQL如下:

SELECT * FROM books WHERE id > 3000000 LIMIT offset, length;
-- offset: 150000 start
-- length: 5000

由于代码执行过慢,这里对代码进行了添加日志观察,看看到底慢在了哪里。根据网上查询的资料来看,应该就是慢在了SQL,实际跟踪下来的结果如下:

关键代码执行时间预期结果实际结果备注
newConn = druidDataSource.getConnection();30ms很快符合预期结果
rs = stmt.executeQuery(sql);12.6s可以接收的慢不符合260s的预期
while (rs.next()) { … }252s超出预料了

根据这个结果,又在网上找了很久,基本总结下来就就是SQL慢,rs.next()慢是错觉。然后博主又做了10组sql的查询结果如下:

SQL执行时间表数据量
SELECT * FROM books WHERE id > 3000000 LIMIT 300000, 500012.576s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 305000, 500012.879s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 310000, 500015.952s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 315000, 500015.541s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 320000, 500013.110s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 325000, 500012.691> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 330000, 500016.411s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 335000, 500011.809s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 340000, 50009.461s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 345000, 500010.374s> 350w

直接执行SQL和上面日志跟踪到的执行时间出入不大,于是准备使用mybaits来看测试看看,测试代码如下

IntStream.range(1, 11).forEach(it -> {
    long l = System.currentTimeMillis();
    booksMapper.getLimit(it * 5000 + 300000);
    long l1 = System.currentTimeMillis();
    System.out.println("耗时:" + (l1 - l) / 1000 + "s");
});

List<Books> getLimit(int offset);

<select id="getLimit" resultMap="BaseResultMap" parameterType="int">
    SELECT * FROM books WHERE id > 3000000 limit #{offset}, 5000
</select>

执行结果如下:

SQL执行时间表数据量
SELECT * FROM books WHERE id > 3000000 LIMIT 305000, 500010.301s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 310000, 500011.130s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 315000, 500012.417s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 320000, 500013.588s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 325000, 500013.810s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 330000, 500013.968s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 335000, 500018.056s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 340000, 500011.202s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 345000, 500018.017s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 350000, 500016.619s> 350w

看到这里的时候跟JDBC对比,发现如果仅仅只是SQL执行跟MyBatis比较,真的没有很大出入。但是MyBatis其实不仅查询了数据,而且还做了数据的封装并且返回。JDBC这里也是做了封装的,为啥差别这么大。真的是代码问题吗?好像结果已经不言而喻了。博主还是不太敢相信,决定在调整一下代码,调整代码如下:

while (rs.next()) {
    // 删除了处理逻辑,这样就不会是封装返回值影响了
}

实际调用结果如下:

执行第几次执行时间表数据量
1200s> 350w
2180s> 350w
3165s> 350w
4185s> 350w
5193s> 350w
6184s> 350w
7178s> 350w
8162s> 350w
9180s> 350w
10191s> 350w

这是不是已经铁的事实,就是拼接问题?不见得吧。比较下来,拼接问题看来并不是很大。耗时还是再rs.next上。

rs.next()的实现就是光标的移动,光标的移动仅仅只是位置的偏移而已,并不产生很多的消耗。这个时候只能提出假设了,假设rs.next并不仅仅是走了光标而且还在数据库内做了什么,并且与我们的SQL有关,那我们SQL本身很慢的话,那这种现状就有解释。于是对SQL调整,调整如下:

SELECT * FROM books a INNER JOIN( SELECT * FROM books WHERE id > 3000000 LIMIT 255000, 5000 ) b ON a.id = b.id

先SQL执行测试10组试试:
执行结果如下:

SQL执行时间表数据量
SELECT * FROM books WHERE id > 3000000 LIMIT 305000, 50004.662s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 310000, 50004.966s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 315000, 50004.407s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 320000, 50004.276s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 325000, 50004.199s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 330000, 50004.422s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 335000, 50004.282s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 340000, 50003.819s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 345000, 50003.813s> 350w
SELECT * FROM books WHERE id > 3000000 LIMIT 350000, 50003.666s> 350w

看起来快了比之前SQL执行快了两倍还要多。不过这里有个问题,我们执行SQL的时候,如果是在客户端里面执行的,他会自动限定查询的返回结果,比如:固定显示200条,其实就是limit 200,这个条件导致我们测试不是那么的准。所以还是继续走程序

先将之前的代码恢复到最开始的状态,然后用这个调整的SQL走10组试试

执行第几次执行时间表数据量
1629.969s> 350w
2607.075s> 350w
3660.476s> 350w
4653.261s> 350w
5679.521s> 350w
6611.962s> 350w
7598.981s> 350w
8604.788s> 350w
9651.673s> 350w
10650.522s> 350w

事实证明,就是优化的SQL在客户端执行看似有用,实际程序内运行,慢了3倍。

JDBC查询比MyBatis慢在哪里?

真的是rs.next吗?

------------------------------------> 待续

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

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

相关文章

Pyqt5 Key value动态创建 QTreeWidget

在自己的应用上&#xff0c;需要根据读取的 值来创建 目录与子页&#xff0c;并打开对应的界面 实现思路 1、定义数组 存放 &#xff5b;&#xff08;Key value index &#xff09;.....&#xff08;Key_n value_n index_n &#xff09;&#xff5d; 2、获取相关数据&#x…

【Java开发】 Spring 09 :Spring Data REST 实现并访问简单的超媒体服务

Spring Data REST 是提供一个灵活和可配置的机制来编写可以通过HTTP公开的简单服务&#xff0c;简单来说&#xff0c;而且可以省去大部分controller和services的逻辑&#xff0c;因为Spring Data REST 已经为你都做好了&#xff0c;目前支持JPA、MongoDB、Neo4j、Solr、Cassand…

Ribbon负载均衡

Ribbon负载均衡 Ribbon是微服务架构中&#xff0c;可以作为负载均衡的技术实现&#xff0c;如下图所示 Ribbon负载均衡 1、消费者发起请求2、被负载均衡拦截器拦截3、将请求信息交给RibbonLoadBanlancerClient4、获取url的服务id5、DynamicServerListLoadBalancer拿到id去eur…

java基础巩固-宇宙第一AiYWM:为了维持生计,架构知识+分布式微服务+高并发高可用高性能知识序幕就此拉开(二:网关balabala)~整起

上集&#xff0c;在架构知识分布式微服务高并发高可用高性能知识序幕就此拉开&#xff08;一&#xff1a;总览篇&#xff09;中&#xff0c;说到了 当用户请求过来时&#xff0c;这个请求或者说URL先到服务调用端【咱们之前的项目中的Controller其实就算是一个服务调用方&#…

VMware ESXi 8.0 SLIC Unlocker 集成网卡驱动和 NVMe 驱动 (集成驱动版)

发布 ESXi 8.0 集成驱动版&#xff0c;在个人电脑上运行企业级工作负载 请访问原文链接&#xff1a;VMware ESXi 8.0 SLIC & Unlocker 集成网卡驱动和 NVMe 驱动 (集成驱动版)&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysi…

【Pytorch】第 3 章 :进行数值估计的蒙特卡洛方法

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

Java ssh框架 mysql实现的进销存管理系统源码+运行教程+文档

今天给大家演示一下一款由sshmysql实现的进销存管理系统&#xff0c;其中struts版本是struts2&#xff0c;这个系统的功能非常完善&#xff0c;简直可以说是牛逼&#xff0c;到了可以用于企业直接商用的地步&#xff0c;此外该项目还带有完整的论文&#xff0c;是Java学习者及广…

Spark 初识

文章目录Spark 初识Spark是什么Apache Spark演变为什么使用Spark全快Spark组件Spark CoreSpark SQLSpark StreamingSpark MLlibSpark GraphXSparkRpySparkspark 在数仓的应用总结Spark 初识 从今天开始我们进入数据仓库的查询引擎篇了&#xff0c;前面我们已经写了大量的文章介…

三分钟了解LAP编程框架

针对Java开发者的灵魂拷问&#xff1a; 1、梳理的流程&#xff0c;关键逻辑是否有遗漏&#xff0c;理解一致吗&#xff1f; 2、设计时&#xff0c;如何更方便的与产品沟通&#xff1f;原有的设计是否有不合理的&#xff1f;绘制的流程图大家都能理解吗&#xff1f; 3、测试时&a…

316页11万字AI赋能智慧水利大数据信息化平台建设和运营解决方案

第一章 系统综述 1.1 项目背景 1.2 系统概述 1.3 需求分析 1.3.1 中心管控需求 1.3.2 前端监测需求 1.4 建设目标 1.5 设计原则 1.6 设计依据 第二章 系统总体设计 2.1 总体设计思路 2.2 架构设计 2.2.1 逻辑架构 2.2.2 系统架构 2.3 关键技术应用 2.4 系统特色…

代码随想录刷题|LeetCode 647. 回文子串 516.最长回文子序列

647. 回文子串 题目链接&#xff1a;https://leetcode.cn/problems/palindromic-substrings/ 思路 动态规划思路 1、确定dp数组 布尔类型的dp[i][j]&#xff1a;表示区间范围[i,j] &#xff08;注意是左闭右闭&#xff09;的子串是否是回文子串&#xff0c;如果是dp[i][j]为tr…

【真的?】用 ChatGPT 写一篇 Python 翻译库博客,可以打 9 分

今天来个大的实践项目&#xff0c;用 ChatGPT 写一篇博客&#xff0c;冲击一下热榜&#xff01; 从零开始玩 ChatGPT⛳️ ChatGPT 亮点⛳️ 账号篇⛳️ 第一次使用⛳️ 用 Python 实现一个英汉互译的小程序⛳️ googletrans 库核心用法⛳️ 再补充一些知识点⛳️ googletrans 和…

功率放大电路和电压放大电路的区别是什么意思

功率放大电路和电压放大电路都属于模拟电路&#xff0c;是工程师日常经常用到的比较常见的模拟电路&#xff0c;很多小白工程师对于功率放大电路和电压放大电路的区别都很好奇&#xff0c;下面就来看看区别有哪些。 图&#xff1a;功率放大电路与电压放大电路对比 1、功能和基本…

docker之网络配置

目录一、网络模式1.bridge模式(默认模式)2.host模式3.初识网络模式二、bridge模式三、host模式四、自定义网络一、网络模式 Docker在创建容器时有四种网络模式&#xff1a;bridge/host/container/none&#xff0c;bridge为默认不需要用–net去指定&#xff0c;其他三种模式需要…

微服务框架 SpringCloud微服务架构 19 文档操作 19.2 修改文档

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构19 文档操作19.2 修改文档19.2.1 修改文档19.2.2 总结19 文档操作 19.2 修…

推荐一款超级好用的工具:uTools详解使用

介绍 uTools 是什么&#xff1f;下载并安装uTools 能做什么&#xff1f;一切皆插件超级面板 uTools 是什么&#xff1f; uTools 是一个极简、插件化、跨平台的现代桌面软件。通过自由选配丰富的插件&#xff0c;打造你得心应手的工具集合。 通过快捷键&#xff08;默认 alt…

红队隧道应用篇之CS正反向连接突破内网(二)

正向连接 环境拓扑图 操作步骤 在CS客户端新建一个TCP协议的监听, 监听端口为4444 创建无状态木马(Windows Executable(S)), 选择上述建立的TCP监听器, 随后将无状态木马放到不出网的内网主机中去运行, 运行后内网主机就会监听本机的4444端口 在web服务器的beacon命令行输入:…

EMQX安装与使用

EMQX文档&#xff1a;https://www.emqx.io/docs/zh/v5.0/ 1.安装 https://www.emqx.io/zh/downloads 找到自己合适的平台和版本安装 ①&#xff1a;后台启动 emqx start启动成功后可以使用 emqx ping 命令检测节点运行状态&#xff0c;返回 pong 则表示正常运行&#xff1a; …

pmp 证书到底有什么用处?

PMP 证书最重要的两个用处&#xff1a;一个是岗位招聘要求&#xff0c;一个是项目招标要求。 一、PMP证书的应用 1、PMP 证书的敲门砖作用 前面说的&#xff0c;PMP 作为项目管理领域的一个权威公认证书&#xff0c;很多行业要求项目管理岗位人才都会加一条"具备PMP 等证…

Redis vs MongoDB

Redis vs MongoDB 通常情况下&#xff0c;应用系统的技术选型&#xff0c;对于如何选择非关系型数据库&#xff0c;是一个不小的挑战。这不仅考验架构师在技术上的广度和深度&#xff0c;同时也考究对业务细节了解和熟悉程度。只有将业务场景、业务特点、数据特征跟具体的技术…