参考 https://blog.csdn.net/xunwei0303/article/details/80241340?utm_source=blogxgwz1
创建多个线程,每个线程处理一批数据。
1. 创建表(mysql)
CREATE TABLE TEST_BATCH_INSERT ( TEST_ID bigint PRIMARY key, TEST_NAME VARCHAR(100), AGE INT(5), CREATE_TIME DATETIME DEFAULT current_timestamp, UPDATE_TIME DATETIME DEFAULT current_timestamp ) comment '测试批量插入';
2. java bean
public class TestBatchInsertInfo { private Long testId; private String testName; private Integer age; private Date createTime; private Date updateTime; // 省略getter/setter }
3. dao
public interface ITestBatchInsertMapper { void batchInsert(List<TestBatchInsertInfo> list); }
4. mapper.xml
<insert id="batchInsert" parameterType="java.util.List"> INSERT INTO TEST_BATCH_INSERT ( TEST_ID, TEST_NAME, AGE, CREATE_TIME, UPDATE_TIME ) VALUES <foreach collection="list" item="log" index= "index" separator =","> ( #{log.testId, jdbcType=NUMERIC}, #{log.testName, jdbcType=VARCHAR}, #{log.age, jdbcType=NUMERIC}, sysdate(), sysdate() ) </foreach> </insert>
5. 多线程
public class TestBatchInsertThread implements Runnable { private ITestBatchInsertMapper testBatchInsertMapper; /** 数据集合 */ private List<TestBatchInsertInfo> list; /** 每个线程处理的起始数据 */ private CountDownLatch begin; /** 每个线程处理的结束数据 */ private CountDownLatch end; public TestBatchInsertThread() { } public TestBatchInsertThread(List<TestBatchInsertInfo> list, CountDownLatch begin, CountDownLatch end, ITestBatchInsertMapper testBatchInsertMapper) { this.list = list; this.begin = begin; this.end = end; this.testBatchInsertMapper = testBatchInsertMapper; } @Override public void run() { try { if (list != null && !list.isEmpty()) { testBatchInsertMapper.batchInsert(list); } // 执行完让线程直接进入等待 begin.await(); } catch (Exception e) { e.printStackTrace(); } finally { // 当一个线程执行完 了计数要减一不然这个线程会被一直挂起 end.countDown(); } } }
6. service
多线程处理的方法是 batchInsertByThread;
普通批量处理的方法是 batchInsert
@Service(value = "testBatchInsertService")
public class TestBatchInsertServiceImpl implements ITestBatchInsertService {
@Autowired
private ITestBatchInsertMapper testBatchInsertMapper;
@Override
@Transactional
public void batchInsertByThread(List<TestBatchInsertInfo> list) throws Exception {
if (list == null || list.isEmpty()) {
return;
}
// 一个线程处理300条数据
int count = 1000;
// 数据集合大小
int listSize = list.size();
// 开启的线程数
int runSize = (listSize / count) + 1;
// 存放每个线程的执行数据
List<TestBatchInsertInfo> newList = null;
// 创建一个线程池,数量和开启线程的数量一样
ExecutorService executor = Executors.newFixedThreadPool(runSize);
// 创建两个个计数器
CountDownLatch begin = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(runSize);
for (int i = 0; i < runSize; i++) {
/* 计算每个线程执行的数据 */
if ((i + 1) == runSize) {
int startIdx = (i * count);
int endIdx = list.size();
newList = list.subList(startIdx, endIdx);
} else {
int startIdx = (i * count);
int endIdx = (i + 1) * count;
newList = list.subList(startIdx, endIdx);
}
TestBatchInsertThread thread = new TestBatchInsertThread(newList, begin, end, testBatchInsertMapper);
executor.execute(thread);
}
begin.countDown();
end.await();
executor.shutdown();
}
@Override
public void batchInsert(List<TestBatchInsertInfo> list) {
if (list == null || list.isEmpty()) {
return;
}
List<TestBatchInsertInfo> tempList = new LinkedList<>();
for (int i = 0; i < list.size(); i++) {
tempList.add(list.get(i));
if (i % 1000 == 0) {
testBatchInsertMapper.batchInsert(tempList);
tempList.clear();
}
}
testBatchInsertMapper.batchInsert(tempList);
}
}
7. junit4 测试方法
import java.util.LinkedList; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.jieshun.springboot.mybatis.MybatisApplication; import com.jieshun.springboot.mybatis.bean.po.TestBatchInsertInfo; import com.jieshun.springboot.mybatis.service.ITestBatchInsertService; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = MybatisApplication.class/*, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT*/) public class TestBatchInsertService { @Autowired private ITestBatchInsertService testBatchInsertService; @Test public void batchInsertByThread() { long startTime = System.currentTimeMillis(); try { List<TestBatchInsertInfo> list = new LinkedList<>(); TestBatchInsertInfo info = null; for (int i = 0; i < 100301; i++) { Integer ig = i; info = new TestBatchInsertInfo(); info.setTestId(ig.longValue()); info.setTestName("test名称_" + i); info.setAge(i); list.add(info); } testBatchInsertService.batchInsertByThread(list); System.out.println("------Batch Insert Success------"); } catch (Exception e) { e.printStackTrace(); } System.out.println("耗时(ms):" + (System.currentTimeMillis() - startTime)); } @Test public void batchInsert() { long startTime = System.currentTimeMillis(); try { List<TestBatchInsertInfo> list = new LinkedList<>(); TestBatchInsertInfo info = null; for (int i = 0; i < 100301; i++) { Integer ig = i; info = new TestBatchInsertInfo(); info.setTestId(ig.longValue()); info.setTestName("test名称_" + i); info.setAge(i); list.add(info); } testBatchInsertService.batchInsert(list); System.out.println("------Batch Insert Success------"); } catch (Exception e) { e.printStackTrace(); } System.out.println("耗时(ms):" + (System.currentTimeMillis() - startTime)); } }
8. springboot 启动类
import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * 应用启动类 * * @author * @date 2018年10月17日 * @since JDK 1.8 */ @SpringBootApplication @EnableTransactionManagement @ComponentScan(basePackages = { "com.jieshun.springboot.mybatis" }) @MapperScan(basePackages = { "com.jieshun.springboot.mybatis.dao" }) public class MybatisApplication { public static void main(String[] args) { SpringApplication.run(MybatisApplication.class, args); } }
相关推荐
- **优化数据读取**:如果数据来自文件,可以使用多线程并行读取,提高数据加载速度。 - **批量操作间隔**:在大量数据插入过程中,适当加入延迟,防止对数据库造成过大压力。 这个"C#大数据批量插入Access程序"的...
C#作为一种强大的编程语言,提供了多种策略来高效地管理大数据并优化多线程应用,以提高性能和用户体验。以下将详细介绍“C#处理大容量数据,及多线程简单应用”这一主题。 首先,当我们面临大量数据时,一个关键的...
在处理大数据时,可能需要考虑分片(Sharding)、分区(Partitioning)或者批量插入(Bulk Insert)等策略,以提高写入效率和查询性能。此外,事务的正确性和一致性也很重要,尤其是在多线程环境下,需要确保数据的...
在Java编程中,多线程技术是处理大数据批量导入或导出的重要手段。它能有效提升程序执行效率,尤其在数据库操作这样的I/O密集型任务中。本项目以"java多线程实现大批量数据导入源码"为题,旨在通过多线程策略将大量...
Java多线程实现数据切割批量执行,实现限流操作。 java线程池Executors实现数据批量操作。 批量异步Executors处理数据,实现限流操作,QPS限流。 线程池调用第三方接口限流实现逻辑。 案例适合: 1.批量处理大数据。...
EasyExcel提供了一种多线程并发读取Excel数据的方式,通过`readSheetHandler`和`executeParallel`方法,可以将读取任务分配到多个线程中执行。每个线程独立处理一部分行数据,这样可以显著提升数据处理速度。 3. *...
6. **考虑使用异步操作**:如果可能,使用线程或异步任务进行批量插入,以免阻塞主线程,提高用户体验。 7. **数据分批**:对于非常大的数据集,可以考虑分批插入,每次插入一部分数据,避免一次性加载全部数据导致...
在"C#大数据效率批量插入Access-demo"这个示例项目中,很可能是提供了一个实际的C#代码示例,演示了如何使用上述方法将大量数据高效地导入到Access数据库。通过分析和学习这个示例,开发者可以了解并掌握在C#环境下...
1. **并发控制不当**:多线程或多个进程同时插入数据时,如果没有适当的并发控制机制,可能会导致数据丢失。 2. **事务管理问题**:如果在事务未提交的情况下就发生异常或者中断,则可能导致部分数据未能成功写入...
在这个场景中,我们将详细探讨如何使用`JdbcTemplate`进行批量插入和删除操作。 批量插入操作在数据库处理大量数据时非常常见,它可以显著提高性能,因为数据库通常会优化批量处理,而不是单独处理每一项。在提供的...
本文将探讨如何优化这一过程,以实现快速插入,并通过具体的Java多线程和MySQL批量插入策略来提升性能。 首先,我们需要理解传统的逐条插入方式在大数据量下效率极低,因为它涉及到频繁的数据库交互,这会消耗大量...
在C#中处理海量数据的批量插入和更新是一项常见的任务,尤其是在大数据应用或者ETL(提取、转换、加载)流程中。尽管ADO.NET在某些方面可能不如JDBC提供那么直观和便捷的批量操作API,但它仍然提供了高效的方法来...
本文将介绍使用Java的多线程技术来提高数据导入效率的方法步骤,以期帮助读者更好地理解并应用这一技术。 ### Java多线程技术 Java中的多线程技术是指在同一个程序中可以同时运行多个线程来执行多个任务。Java提供...
一、问题 现有a表和b表,两张mysql数据库的表,需要把两张表的数据取共同字段,合并并导入es中,其中a表共有数据1000条,b表共有数据1200条,a表和b表的主键id都是从1开始递增的,结果导入的时候显示成功导入2200条...
Java链接HBase进行增删改查操作是大数据领域常见的任务,尤其在处理大规模分布式存储时。HBase,作为Apache Hadoop生态...在实际项目中,你可能需要根据需求调整这些操作,比如增加过滤器、使用多线程处理批量操作等。
同时,数据库端可能需要使用批量插入或者存储过程来提高插入速度。此外,预处理SQL语句、索引优化以及适当的事务管理也是提升性能的关键。 其次,将千万级别的大数据导出到Excel,通常会遇到Excel文件大小限制和...
总结起来,Java在处理大数据时,主要采用了分批读取、批量入库、多线程并行处理和线程池管理等策略。这些技术能够有效优化内存使用,提高处理效率,同时防止服务器过载。在实际应用中,需要根据服务器配置和数据量...
通过批处理操作,JdbcBatchItemWriter 可以高效地执行大量的数据库插入、更新操作,提高性能。 ### 5. 批处理作业配置 在 Spring Batch 中,作业(Job)由一个或多个步骤(Step)组成。每个步骤通常包含读取、处理...
- 使用多线程并行处理:可以将数据分成多个部分,每个部分在单独的线程中导入。 - 控制批大小:合理设置批量操作的大小,避免内存压力过大或过小导致性能问题。 - 合理配置HBase:调整HBase的Region大小,负载...