当前位置: 首页 > article >正文

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

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

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.kler.cn/a/403746.html

相关文章:

  • 五天SpringCloud计划——DAY1之mybatis-plus的使用
  • Perl 简介
  • AI一键生成原创花卉印花图案——创新与效率的结合
  • 简单工厂模式、方法工厂模式
  • summernote富文本批量上传音频,视频等附件
  • Python 绘图工具详解:使用 Matplotlib、Seaborn 和 Pyecharts 绘制散点图
  • MyBatis的resultType和resultMap区别
  • 力扣 LeetCode 112. 路径总和(Day8:二叉树)
  • 失落的Apache JDBM(Java Database Management)
  • 【项目实战】基于 LLaMA-Factory 通过 LoRA 微调 Qwen2
  • 2024信创数据库TOP30之蚂蚁集团OceanBase
  • 最新智能AI问答运营系统(SparkAi)一站式AIGC系统,GPT-4.0/GPT-4o多模态模型+联网搜索提问+AI绘画+管理后台,用户会员套餐
  • Excel中批量替换字符大PK:Excel VS. Python
  • c ++零基础可视化——vector
  • WebSocket详解、WebSocket入门案例
  • React渲染流程与更新diff算法
  • AMD(Xilinx) FPGA配置Flash大小选择
  • Linux:权限相关知识详解
  • 基于yolov8、yolov5的茶叶等级检测识别系统(含UI界面、训练好的模型、Python代码、数据集)
  • hhdb数据库介绍(9-26)
  • 当mysql的slave无法同步master数据时,如何基本不断业务重置主从同步关系
  • MySQL社区版的启动与连接
  • 数据集-目标检测系列- 花卉 鸡蛋花 检测数据集 frangipani >> DataBall
  • TensorFlow 2.0 windows11 GPU 训练环境配置
  • Unity3D空中突袭(1)场景导入
  • 全面认识AI Agent,一文读懂AI智能体的架构指南