Краткое обсуждение метода пакетной вставки MyBatis: обработка 100 000 фрагментов данных занимает всего 2 секунды.
Краткое обсуждение метода пакетной вставки MyBatis: обработка 100 000 фрагментов данных занимает всего 2 секунды.

Предисловие: Функция «Пакетная доставка» сегодня является одной из наиболее распространенных бизнес-функций в нашей повседневной работе.Старшийприди один MyBatis Сводка пакетной вставки, и в то же время 3 Проведите тест производительности этого метода реализации и соответствующий анализ принципов.

Снова входя в процветающий мир, толпы толпятся, глаза пусты, а вера вечна, все они за Китай. 

Оглавление

Подготовка

1. Циклическая одиночная вставка

2. Пакетная вставка MP

① Реализация контроллера

②Реализация уровня бизнес-логики

③ Реализация уровня сохранения данных.

Тест производительности МП

Анализ исходного кода MP

3. Собственная пакетная вставка

① Расширение уровня бизнес-логики

② Расширение уровня сохранения данных

③ Добавьте UserMapper.xml.

Собственный тест производительности пакетной вставки

Анализ недостатков

Подвести итог


Давайте сначала кратко об этом поговорим 3 种Пакетная Функции вставки:

  1. Цикл одинарной вставки;
  2. MP Пакетная вставка Функция;
  3. Родной Пакетная вставка Функция。

Подготовка

Прежде чем мы начнем, давайте сначала создадим базу данных и протестируем данные. Выполняемый сценарий SQL выглядит следующим образом:

Язык кода:javascript
копировать
-- ----------------------------
-- создать базу данных
-- ----------------------------
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP DATABASE IF EXISTS `testdb`;
CREATE DATABASE `testdb`;
USE `testdb`;

-- ----------------------------
-- создавать user поверхность
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `createtime` datetime NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- добавить в тестовых данных
-- ----------------------------
INSERT INTO `user` VALUES (1, «Чжао Юнь», '123456', '2021-09-10 18:11:16');
INSERT INTO `user` VALUES (2, «Чжан Фэй», '123456', '2021-09-10 18:11:28');
INSERT INTO `user` VALUES (3, «Гуань Юй», '123456', '2021-09-10 18:11:34');
INSERT INTO `user` VALUES (4, «Лю Бэй», '123456', '2021-09-10 18:11:41');
INSERT INTO `user` VALUES (5, «Цао Цао», '123456', '2021-09-10 18:12:02');

SET FOREIGN_KEY_CHECKS = 1;

Конечный эффект от базы данных следующий:

1. Циклическая одиночная вставка

Далее мы будем использовать Spring Boot проект,Пакетная вставка 10W данные для проверки времени выполнения каждого метода отдельно.

(Тестовый) основной код для одной вставки в цикл выглядит следующим образом:

Язык кода:javascript
копировать
import com.example.demo.model.User;
import com.example.demo.service.impl.UserServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class UserControllerTest {

    // Максимальное количество циклов
    private static final int MAXCOUNT = 100000;

    @Autowired
    private UserServiceImpl userService;

    /**
     * Петля одинарная вставка
     */
    @Test
    void save() {
        long stime = System.currentTimeMillis(); // Время начала статистики
        for (int i = 0; i < MAXCOUNT; i++) {
            User user = new User();
            user.setName("test:" + i);
            user.setPassword("123456");
            userService.save(user);
        }
        long etime = System.currentTimeMillis(); // Время окончания статистики
        System.out.println("Время выполнения:" + (etime - stime));
    }
}

Запуск вышеуказанной программы занял 88574 миллисекунды, как показано на рисунке ниже:

2. Пакетная вставка MP

Существует три основных класса реализации функции «Пакетная вставка MP»: UserController (контроллер).、UserServiceImpl (класс реализации бизнес-логики), UserMapper (класс отображения базы данных),Процесс их вызова выглядит следующим образом:

Обратите внимание, что для реализации этого метода требуется следующее содержимое в файле pom.xml, добавленное в MP рама, открытая pom.xml:

Язык кода:javascript
копировать
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>mybatis-plus-latest-version</version>
</dependency>

Примечание. mybatis-plus-latest-version представляет собой номер последней версии платформы MP. Вы можете посетить https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter, чтобы запросить номер последней версии. но при использовании не забудьте заменить «mybatis-plus-latest-version» выше на конкретный номер версии, например 3.4.3, чтобы правильно представить структуру.

Для получения дополнительной информации о структуре MP посетите ее официальный сайт: https://baomidou.com/guide/.

① Реализация контроллера

Язык кода:javascript
копировать
import com.example.demo.model.User;
import com.example.demo.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

@RestController
@RequestMapping("/u")
public class UserController {

    @Autowired
    private UserServiceImpl userService;

    /**
     * Пакетная вставка (под заказ)
     */
    @RequestMapping("/mysavebatch")
    public boolean mySaveBatch(){
        List<User> list = new ArrayList<>();
        // обращатьсядобавить в (пользовательские) данные
        for (int i = 0; i < 1000; i++) {
            User user = new User();
            user.setName("test:"+i);
            user.setPassword("123456");
            list.add(user);
        }
        return userService.saveBatchCustom(list);
    }
}

②Реализация уровня бизнес-логики

Язык кода:javascript
копировать
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User>
        implements UserService {

    @Autowired
    private UserMapper userMapper;

    public boolean saveBatchCustom(List<User> list){
        return userMapper.saveBatchCustom(list);
    }
}

③ Реализация уровня сохранения данных.

Язык кода:javascript
копировать
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.model.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface UserMapper extends BaseMapper<User>{

    boolean saveBatchCustom(List<User> list);
}

После реализации приведенного выше кода мы можем использовать MP Для реализации пакетной вставка функции, но помимо конкретного кода реализации в этой статье нам также необходимо знать эффективность выполнения каждого метода, поэтому далее мы напишем MP тестовый код.

Тест производительности МП

Язык кода:javascript
копировать
import com.example.demo.model.User;
import com.example.demo.service.impl.UserServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class UserControllerTest {

    // Максимальное количество циклов
    private static final int MAXCOUNT = 100000;

    @Autowired
    private UserServiceImpl userService;

    /**
     * MP Пакетная вставка
     */
    @Test
    void saveBatch() {
        long stime = System.currentTimeMillis(); // Время начала статистики
        List<User> list = new ArrayList<>();
        for (int i = 0; i < MAXCOUNT; i++) {
            User user = new User();
            user.setName("test:" + i);
            user.setPassword("123456");
            list.add(user);
        }
        // MP Пакетная вставка
        userService.saveBatch(list);
        long etime = System.currentTimeMillis(); // Время окончания статистики
        System.out.println("Время выполнения:" + (etime - stime));
    }
}

Выполнение вышеуказанной программы заняло в общей сложности 6088 миллисекунд, как показано на рисунке ниже:

Из приведенных выше результатов видно, что использование MP из Пакетная функция вставки (вставить данные 10W bar), его производительность улучшена по сравнению с производительностью одиночной вставки в цикл. 14.5 раз.

Анализ исходного кода MP

По времени выполнения MP и одиночной вставке цикла мы видим, что использование MP не является выполнением одного цикла, как думают некоторые друзья. Чтобы объяснить эту проблему более четко, мы рассмотрели исходный код MP.

Основным кодом реализации MP является метод saveBatch. Исходный код этого метода выглядит следующим образом:

Давайте продолжим следить за перегруженным методом saveBatch:

Как видно из приведенного выше исходного кода, MP заключается в разделении данных, подлежащих выполнению, на N порция, каждая порция 1000 полоски, каждая полная 1000 Статья будет выполнена один раз. вставка,所以它из性能要比Петля одинарная вставкаиз性能高很多。

Так почему же нам нужно выполнять его пакетами, а не все сразу? Не волнуйтесь, мы поймем, когда рассмотрим третий метод реализации.

3. Собственная пакетная вставка

Родной Пакетная метод доставки заключается в том, чтобы полагаться на MyBatis в foreach тег, объединяющий данные в собственный insert Оператор выполняется один раз, а основной код реализации выглядит следующим образом.

① Расширение уровня бизнес-логики

существовать UserServiceImpl добавить в saveBatchByNative Метод, код реализации следующий:

Язык кода:javascript
копировать
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Autowired
    private UserMapper userMapper;

    public boolean saveBatchByNative(List<User> list) {
        return userMapper.saveBatchByNative(list);
    }

}

② Расширение уровня сохранения данных

существовать UserMapper добавить в saveBatchByNative Метод, код реализации следующий:

Язык кода:javascript
копировать
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.model.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface UserMapper extends BaseMapper<User> {

    boolean saveBatchByNative(List<User> list);
}

③ Добавьте UserMapper.xml.

Создайте файл UserMapper.xml и используйте тег foreach для объединения SQL. Конкретный код реализации выглядит следующим образом:

Язык кода:javascript
копировать
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <insert id="saveBatchByNative">
        INSERT INTO `USER`(`NAME`,`PASSWORD`) VALUES
        <foreach collection="list" separator="," item="item">
            (#{item.name},#{item.password})
        </foreach>
    </insert>

</mapper>

После вышеописанных действий наша родная Пакетная Функция вставки почти реализована. Далее используем Модульное. Хочу проверить эффективность выполнения этого метода.

Собственный тест производительности пакетной вставки

Язык кода:javascript
копировать
import com.example.demo.model.User;
import com.example.demo.service.impl.UserServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class UserControllerTest {

    // Максимальное количество циклов
    private static final int MAXCOUNT = 100000;

    @Autowired
    private UserServiceImpl userService;
    
    /**
     * Родной сплайсинг SQL,Пакетная вставка
     */
    @Test
    void saveBatchByNative() {
        long stime = System.currentTimeMillis(); // Время начала статистики
        List<User> list = new ArrayList<>();
        for (int i = 0; i < MAXCOUNT; i++) {
            User user = new User();
            user.setName("test:" + i);
            user.setPassword("123456");
            list.add(user);
        }
        // Пакетная вставка
        userService.saveBatchByNative(list);
        long etime = System.currentTimeMillis(); // Время окончания статистики
        System.out.println("Время выполнения:" + (etime - stime));
    }
}

Однако когда мы запускаем программу, происходит следующее:

Нани? Выполнение программы фактически сообщило об ошибке.

Анализ недостатков

Как видно из приведенного выше сообщения об ошибке, когда мы используем собственный метод для объединения фрагментов данных мощностью 10 Вт в один SQL для выполнения, объединенный SQL слишком велик (4,56 МБ), что приводит к ошибке выполнения программы, поскольку по умолчанию максимальный размер SQL, который может выполнить MySQL (размер), составляет 4 МБ, поэтому программа сообщила об ошибке.

Это оригинальная Пакетная Недостатки метода вставки и почему MP Причина пакетного выполнения состоит в том, чтобы предотвратить запуск базы данных «Максимальное», когда программа существует. исполнение SQL Это приводит к тому, что выполнение программы сообщает об ошибке.

решение

Конечно, мы также можем решить проблему ошибок, установив максимальное выполнение SQL MySQL. Команда настройки выглядит следующим образом:

Язык кода:javascript
копировать
-- Установить максимальное исполнение SQL для 10M
set global max_allowed_packet=10*1024*1024;

Как показано ниже:

ПРИМЕЧАНИЕ. Для приведенной выше команды требуется наличие MySQL Выполняется в подключенном клиенте.

Но приведенное выше решение по-прежнему лечит симптомы, а не первопричину.,потому чтодля我们无法预测程序中最大из执行 SQL Насколько он велик, то наиболее универсальный метод — распределить выполнение Пакетная метод вставки (то есть типа MP реализовано).

Когда мы устанавливаем максимальный размер исполняемого SQL-кода MySQL равным 10 МБ и запускаем приведенный выше код модульного теста, результаты выполнения будут следующими:

Подвести итог

В этой статье мы представили MyBatis Пакетная вставкаиз 3 метод, среди которого циклическая одиночная вставка имеет самую низкую производительность и является наименее желательной для использования; MyBatis сплайсинг родной SQL Метод однократной вставки имеет самую высокую производительность, но этот метод может вызвать ошибки выполнения программы (запуск максимального выполнения базы данных). SQL ограничение размера), поэтому, учитывая вышеуказанные обстоятельства, вы можете рассмотреть возможность использования MP из Пакетная вставка Функция。

Наконец Старший Я считаю, что все, должно быть, заплатили плату за обучение MyBatis Пакетная 3 метода вставки и метод, который занимает всего 2 секунды для 100 000 фрагментов данных, сосредоточьтесь на Старший Не теряйтесь В следующем выпуске я научу вас практическим навыкам Более~~.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose