使用数据库批量插入与循环单个插入:优势与区别

news2024/11/24 1:00:50

在开发数据库应用程序时,插入大量数据是一个常见的需求。无论是数据初始化、数据迁移还是日志记录,插入操作的性能和可靠性都是至关重要的。本文将探讨两种常见的插入方法:数据库批量插入和使用循环单个插入,分析它们的优势和区别,并提供示例代码。

1. 批量插入

批量插入是指在一次数据库操作中插入多条记录。这种方法在处理大量数据时表现出显著的性能优势。以下是批量插入的主要优势:

1.1 性能提升
  • 减少网络开销:批量插入可以减少与数据库服务器的网络通信次数。通常,一次网络通信的成本远高于数据库内部的处理成本。
  • 减少事务管理开销:在一个事务中批量插入多条记录可以减少事务的管理和提交次数,提高事务处理的效率。
  • 减少数据库日志开销:数据库的日志记录也会减少,因为只需要记录一次插入操作,而不是多次。
1.2 简化代码
  • 代码简洁:批量插入的代码更加简洁,减少了很多重复的插入逻辑,易于编写和维护。
  • 逻辑统一:所有的插入操作都在一个SQL语句中完成,逻辑更加统一,不容易出错。
1.3 示例代码

假设我们有一个Student类和一个StudentMapper接口,使用MyBatis框架进行批量插入。

Student类

public class Student {
    private String name;
    private int age;
    private String addr;
    private int addrNum;

    // Getters and Setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }

    public int getAddrNum() {
        return addrNum;
    }

    public void setAddrNum(int addrNum) {
        this.addrNum = addrNum;
    }
}

StudentMapper接口

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface StudentMapper {
    @Insert("<script>" +
            "insert into student (name, age, addr, addr_num) values " +
            "<foreach collection='studentList' item='item' separator=','>" +
            "  (#{item.name}, #{item.age}, #{item.addr}, #{item.addrNum})" +
            "</foreach>" +
            "</script>")
    int insertSplice(@Param("studentList") List<Student> studentList);
}

Service类

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.ArrayList;
import java.util.List;

public class StudentService {
    private final SqlSessionFactory sqlSessionFactory;

    public StudentService(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    public int insertStudents(List<Student> studentList) {
        try (SqlSession session = sqlSessionFactory.openSession()) {
            StudentMapper mapper = session.getMapper(StudentMapper.class);
            int result = mapper.insertSplice(studentList);
            session.commit();
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    public static void main(String[] args) {
        // 初始化SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = ...; // 你的初始化代码

        StudentService service = new StudentService(sqlSessionFactory);

        List<Student> studentList = new ArrayList<>();
        Student student1 = new Student();
        student1.setName("Alice");
        student1.setAge(20);
        student1.setAddr("New York");
        student1.setAddrNum(1);
        studentList.add(student1);

        Student student2 = new Student();
        student2.setName("Bob");
        student2.setAge(22);
        student2.setAddr("Los Angeles");
        student2.setAddrNum(2);
        studentList.add(student2);

        int result = service.insertStudents(studentList);
        System.out.println("插入结果: " + result);
    }
}

2. 循环单个插入

循环单个插入是指在一个循环中逐条插入记录。这种方法适用于需要灵活处理每条记录的插入逻辑,或者插入数据量较小且需要逐条处理错误的场景。以下是循环单个插入的主要优势:

2.1 灵活性
  • 灵活处理:可以在插入每条记录时进行更多的逻辑判断和处理,例如验证数据的有效性、进行复杂的业务逻辑等。
  • 错误处理:可以逐条处理插入时的错误,如果某一条记录插入失败,可以立即捕获并处理,而不是整个批量操作失败。
2.2 事务管理
  • 精细控制:可以更精细地控制事务的提交时间。例如,可以在插入若干条记录后提交一次事务,而不是一次性提交所有记录。
2.3 适合小数据量
  • 直观易懂:对于数据量较小的插入操作,单个插入的代码更加直观和易于理解。
2.4 示例代码

假设我们有一个Student类和一个StudentMapper接口,使用MyBatis框架进行单个插入。

Student类

public class Student {
    private String name;
    private int age;
    private String addr;
    private int addrNum;

    // Getters and Setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }

    public int getAddrNum() {
        return addrNum;
    }

    public void setAddrNum(int addrNum) {
        this.addrNum = addrNum;
    }
}

StudentMapper接口

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;

public interface StudentMapper {
    @Insert("insert into student (name, age, addr, addr_num) values (#{name}, #{age}, #{addr}, #{addrNum})")
    int insertStudent(Student student);
}

Service类

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.ArrayList;
import java.util.List;

public class StudentService {
    private final SqlSessionFactory sqlSessionFactory;

    public StudentService(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    public int insertStudents(List<Student> studentList) {
        try (SqlSession session = sqlSessionFactory.openSession()) {
            StudentMapper mapper = session.getMapper(StudentMapper.class);
            int result = 0;
            for (Student student : studentList) {
                result += mapper.insertStudent(student);
            }
            session.commit();
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    public static void main(String[] args) {
        // 初始化SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = ...; // 你的初始化代码

        StudentService service = new StudentService(sqlSessionFactory);

        List<Student> studentList = new ArrayList<>();
        Student student1 = new Student();
        student1.setName("Alice");
        student1.setAge(20);
        student1.setAddr("New York");
        student1.setAddrNum(1);
        studentList.add(student1);

        Student student2 = new Student();
        student2.setName("Bob");
        student2.setAge(22);
        student2.setAddr("Los Angeles");
        student2.setAddrNum(2);
        studentList.add(student2);

        int result = service.insertStudents(studentList);
        System.out.println("插入结果: " + result);
    }
}

3. 优势与区别总结
特性批量插入循环单个插入
性能高(减少网络开销、事务管理开销、日志开销)低(多次网络通信、事务管理开销、日志开销)
代码简洁性高(一次SQL语句完成所有插入)低(需要循环和多次调用插入方法)
错误处理低(所有记录一起处理)高(逐条处理错误)
事务管理低(一次性提交所有记录)高(可以逐条提交或分批提交)
灵活性低(无法在插入时进行复杂逻辑)高(可以在插入时进行复杂逻辑)
适用场景大数据量、性能要求高小数据量、需要灵活处理和错误处理
4. 选择合适的插入方法

选择批量插入还是循环单个插入,取决于你的具体需求和应用场景:

  • 如果需要高效插入大量数据,且数据格式一致,建议使用批量插入。
  • 如果需要灵活处理每条记录的插入逻辑,或者插入数据量较小且需要逐条处理错误,建议使用循环单个插入。
5. 结论

在数据库插入操作中,批量插入和循环单个插入各有优劣。批量插入能够显著提升性能,适用于大数据量的场景;而循环单个插入则更加灵活,适合小数据量和需要逐条处理错误的场景。

希望你喜欢这篇文章!请点关注和收藏吧。你的关注和收藏会是我努力更新的动力,祝关注和收藏的帅哥美女们今年都能暴富。如果有更多问题,欢迎随时提问

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

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

相关文章

RabbitMQ高可用延迟消息惰性队列

目录 生产者确认 消息持久化 消费者确认 TTL延迟队列 TTL延迟消息 惰性队列 生产者确认 生产者确认就是&#xff1a;发送消息的人&#xff0c;要确保消息发送给了消息队列&#xff0c;分别是确保到了交换机&#xff0c;确保到了消息队列这两步。 1、在发送消息服务的ap…

将django+vue项目发布部署到服务器

1.部署django后端服务 部署架构 1.1 下载依赖插件 pip3.8 freeze > requirements.txt1.2 安装依赖插件 pip3 install -r requirements.txt1.3 安装mysql数据库 apt install mysql-server初始化数据库 CREATE USER admin% IDENTIFIED WITH mysql_native_password BY 123…

论文阅读:SIMBA: single-cell embedding along with features

Chen, H., Ryu, J., Vinyard, M.E. et al. SIMBA: single-cell embedding along with features. Nat Methods 21, 1003–1013 (2024). 论文地址&#xff1a;https://doi.org/10.1038/s41592-023-01899-8 代码地址&#xff1a;https://github.com/pinellolab/simba. 摘要 大多…

商业物联网:拥抱生产力的未来

在现代商业格局中&#xff0c;数据占据至高无上的地位。物联网&#xff08;IoT&#xff09;站在这场数字革命的前沿&#xff0c;将以往模糊不清的不确定因素转变为可衡量、可付诸行动的深刻见解。物联网技术为日常物品配备传感器与连接功能&#xff0c;使其能够实时收集并传输数…

【FRP 内网穿透 从0到1 那些注意事项】

【摘要】 最近跟第三方团队调试问题&#xff0c;遇到一个比较烦的操作。就是&#xff0c;你必须要发个版到公网环境&#xff0c;他们才能链接到你的接口地址&#xff0c;才能进行调试。按理说&#xff0c;也没啥&#xff0c;就是费点时间。但是&#xff0c;在调试的时候&#…

最新Kali安装详细版教程(附安装包,傻瓜式安装教程)

本文主要详细介绍 kali 的安装过程&#xff0c;以及安装完成后的基本设置&#xff0c;比如安装增强工具&#xff0c;安装中文输入法以及更新升级等操作。 文章目录 实验环境准备工作步骤说明安装虚拟机安装 Kali安装增强工具安装中文输入法更新升级 实验环境 VMware &#x…

【山大909算法题】2014-T1

文章目录 1.原题2.算法思想3.关键代码4.完整代码5.运行结果 1.原题 为带表头的单链表类Chain编写一个成员函数Reverse&#xff0c;该函数对链表进行逆序操作&#xff08;将链表中的结点按与原序相反的顺序连接&#xff09;&#xff0c;要求逆序操作就地进行&#xff0c;不分配…

论文浅尝 | MindMap:知识图谱提示激发大型语言模型中的思维图(ACL2024)

笔记整理&#xff1a;和东顺&#xff0c;天津大学硕士&#xff0c;研究方向为软件缺陷分析 论文链接&#xff1a;https://aclanthology.org/2024.acl-long.558/ 发表会议&#xff1a;ACL 2024 1. 动机 虽然大语言模型&#xff08;LLMs&#xff09;已经在自然语言理解和生成任务…

Win11 22H2/23H2系统11月可选更新KB5046732发布!

系统之家11月22日报道&#xff0c;微软针对Win11 22H2/23H2版本推送了2024年11月最新可选更新补丁KB5046732&#xff0c;更新后&#xff0c;系统版本号升至22621.4541和22631.4541。本次更新后系统托盘能够显示缩短的日期和时间&#xff0c;文件资源管理器窗口很小时搜索框被切…

SpringSecurity创建一个简单的自定义表单的认证应用

1、SpringSecurity 自定义表单 在 Spring Security 中创建自定义表单认证应用是一个常见的需求&#xff0c;特别是在需要自定义登录页面、认证逻辑或添加额外的表单字段时。以下是一个详细的步骤指南&#xff0c;帮助你创建一个自定义表单认证应用。 2、基于 SpringSecurity 的…

Cloud Native 云原生后端的开发注意事项

在云原生后端开发里&#xff0c;数据管理和存储这块得好好弄。数据库选型得综合考虑&#xff0c;像关系型数据有复杂查询需求就选 MySQL、PostgreSQL&#xff0c;海量非结构化数据就可以考虑 MongoDB、Cassandra 这些。设计数据库得遵循规范化原则&#xff0c;像设计电商订单表…

通达OA前台submenu.php存在SQL注入漏洞(CVE-2024-10600)

通达OA前台submenu.php存在SQL注入漏洞(CVE-2024-10600) pda/appcenter/submenu.php 未包含inc/auth.inc.php且 $appid 参数未用’包裹导致前台SQL注入 影响范围 v2017-v11.6 fofa app"TDXK-通达OA" && icon_hash"-759108386"poc http://url…

TCP连接(三次握手)(四次挥手)

建立TCP连接&#xff08;三次握手&#xff09; 以下是简单阐述 在确定目标服务器 IP 地址后&#xff0c;则经历三次握手建立TCP 连接 三次握手 代表客户端和服务端 之间的传递信息有三次 A说&#xff1a;我想和你聊天 &#xff0c;你能听到我说话吗 B说&#xff1a;我可以听到…

【MySQL实战45讲笔记】基础篇——事务隔离

系列文章 基础篇——MySQL 的基础架构 基础篇——redo log 和 binlog 目录 系列文章1. 事务隔离1.1 隔离性与隔离级别1.2 如何实现事务隔离1.3 事务的启动方式1.4 思考&#xff1a; 使用什么方案来避免长事务 1. 事务隔离 简单来说&#xff0c;事务就是要保证一组数据库操作&…

upload-labs-master第12关详细教程

成功了别忘了回来留下你的评论哦&#xff0c;嘻嘻 目录 环境配置闯关 环境配置 需要的东西 phpstudy-2018 链接&#xff1a; https://pan.baidu.com/s/1D9l13XTQw7o6A8CSJ2ff9Q 提取码&#xff1a;0278 32位 vc9和11运行库 链接&#xff1a; https://pan.baidu.com/s/1pBV3W…

Mac 修改默认jdk版本

当前会话生效 这里演示将 Java 17 版本降低到 Java 8 查看已安装的 Java 版本&#xff1a; 在终端&#xff08;Terminal&#xff09;中运行以下命令&#xff0c;查看已安装的 Java 版本列表 /usr/libexec/java_home -V设置默认 Java 版本&#xff1a; 找到 Java 8 的安装路…

uniapp奇怪bug汇总

H5端请求api文件夹接口报错 踩坑指数&#xff1a;5星 小程序、APP之前都是用api文件夹的接口引用调用&#xff0c;在h5端启动时报错&#xff0c;研究半天&#xff0c;发现把api文件夹名字改成apis就能调用&#xff0c;就像是关键字一样无法使用。 import authApi from /api/…

交换机配置从IP(Switch Configuration from IP)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…

大语言模型---ReLU函数的计算过程及其函数介绍

文章目录 1. 概要2. ReLU定义 1. 概要 **ReLU 作用&#xff1a;**主要用于为神经网络引入非线性能力&#xff0c;作用是将输入中的整数保留原值&#xff0c;负数置为 0。 从而在层与层之间引入非线性&#xff0c;使神经网络能够拟合复杂的非线性关系。 **ReLU使用场景&#xf…

QT如何共享文件+拷贝文件

QString sharedFolderPathImg "\\\\" IP "/profileImage/"; // 更换为你的共享文件夹路径QDir dirImg(sharedFolderPathImg);dirImg.setFilter(QDir::NoDotAndDotDot | QDir::AllEntries);QVector<QString> curFileEntryArrayImg dirImg.entryList…