- 浏览: 524045 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (422)
- 重要 (12)
- BUG解决备忘录 (32)
- 环境搭建 (17)
- 开源组件 (4)
- 数据库 (16)
- 设计模式 (4)
- 测试 (3)
- javascript (5)
- Android (14)
- jdk相关 (9)
- struts2 (10)
- freemark (3)
- 自定义扩展及工具类 (5)
- jdk5新特性及java基础 (13)
- ssh及其他框架 (15)
- linux (32)
- tcp-ip http协议 (8)
- 服务器集群与负载均衡 (34)
- 项目管理相关 (11)
- 实用小技术 (10)
- 架构相关 (14)
- firefox组件 (11)
- spider (6)
- 产品设计 (11)
- PHP (1)
- ws (4)
- lucene (10)
- 其他 (2)
- BI (1)
- NoSQL (3)
- gzip (1)
- ext (4)
- db (6)
- socket (1)
- 源码阅读 (2)
- NIO (2)
- 图片处理 (1)
- java 环境 (2)
- 项目管理 (4)
- 从程序员到项目经理(一):没有捷径 (1)
- bug (1)
- JAVA BASE (8)
- 技术原理 (0)
- 新框架新技术 (1)
- 量化与python (1)
- 系统编程 (0)
- C语言 (0)
- 汇编 (0)
- 算法 (0)
最新评论
-
hyspace:
别逗了,最后一个算法根本不是最优的,sort(function ...
数组去重——一道前端校招试题 -
washingtin:
楼主能把策略和路由的类代码贴出来吗
Spring + iBatis 的多库横向切分简易解决思路 -
sdyjmc:
初略看了一下,没有闹明白啊,均衡负载使用Nginx,sessi ...
J2EE集群原理 I -
shandeai520:
谢谢大神!请教大神一个问题:假如我有三台服务器,连接池的上限是 ...
集群和数据库负载均衡的研究 -
hekuilove:
给lz推荐一下apache commonsStringUtil ...
request 获取 ip
昨
天做了一个东西,要实现解析txt文件,然后入库的功能。开始试验了一下单线程插入,速度实在太慢了,半个小时才插入了2W多条数据,后来改用Java的
线程池启用了30个线程,并发的执行,插入100W条数据用了一个多小时。后来又对业务层的事务做了一些调整,每1000条insert之后才提交一次,
一共开了20个线程,最后100W条数据入库一共用了14分钟不到,平均一分钟7.1W条左右。 代码如下:
- /**
- * 分析Apache日志的定时任务.每天运行数次.
- *
- * @author <a href="mailto:HL_Qu@hotmail.com">Along</a>
- *
- * @version $Revision$
- *
- * @since 2009-2-9
- */
- public class ApacheLogAnalysisTask {
- /**
- * Logger for this class
- */
- private static final Log logger = LogFactory.getLog(ApacheLogAnalysisTask.class);
-
- //总线程数
- private static final int THREAD_COUNT = 20;
-
- //每个线程插入的日志数
- private static final long LOG_COUNT_PER_THREAD = 1000;
-
- //日志文件的位置
- private static final String LOG_FILE = Property.LOG_FILE_PATH + "formatLog.txt";
-
- private IObjectActionDetailService objectActionDetailService;
-
- public void setObjectActionDetailService(IObjectActionDetailService objectActionDetailService) {
- this.objectActionDetailService = objectActionDetailService;
- }
- public void execute() {
- this.multiAnalysisLog();
- }
-
- private void multiAnalysisLog() {
- ExecutorService exePool = Executors.newFixedThreadPool(THREAD_COUNT);
-
- FileReader fr = null;
- BufferedReader br = null;
- long beginLine = 1;
- long endLine = 0;
- String logFileBack = Property.LOG_FILE_PATH +
"/formatLog_" + DateUtil.getSystemCurrentDate() + "_" +
System.currentTimeMillis() + ".txt";
-
- try {
- //文件拷贝出来一个新的,并将原先的删除.
- FileUtil.copyfile(LOG_FILE, logFileBack, true);
- FileUtil.deleteFile(LOG_FILE);
- System.out.println(logFileBack);
-
- fr = new FileReader(logFileBack);
- br = new BufferedReader(fr);
-
- while ((br.readLine()) != null){
- endLine++;
-
- //每个线程分配固定的行数
- if((endLine - beginLine + 1) == LOG_COUNT_PER_THREAD) {
- exePool.execute(new AnalysisLogTask(logFileBack, beginLine, endLine));
- beginLine = endLine + 1;
- }
- }
-
- //最后一个线程
- if (endLine > beginLine) {
- exePool.execute(new AnalysisLogTask(logFileBack, beginLine, endLine));
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (br != null) {
- try {
- br.close();
- br = null;
- } catch (IOException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- }
- }
-
- if (fr != null) {
- try {
- fr.close();
- fr = null;
- } catch (IOException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- }
- }
-
- exePool.shutdown();
- while (true) {
- if (exePool.isTerminated()) {
- System.out.println("ShutDown");
- FileUtil.deleteFile(logFileBack);
- break;
- }
- }
-
- }
- }
-
- private class AnalysisLogTask implements Runnable {
- //起始行
- private long beginLine;
-
- //结束行
- private long endLine;
-
- private String logFilePath;
- public AnalysisLogTask(String logFilePath, long beginLine, long endLine) {
- super();
- this.logFilePath = logFilePath;
- this.beginLine = beginLine;
- this.endLine = endLine;
- }
- @Override
- public void run() {
- FileReader fr = null;
- BufferedReader br = null;
- String tempStr = null;
- String[] tempArray = null;
- long currentLine = 0;
- List <ObjectActionDetail> resultList = new ArrayList<ObjectActionDetail>();
-
- ObjectActionDetail tempObjectActionDetailVO = null;
- try {
- fr = new FileReader(logFilePath);
- br = new BufferedReader(fr);
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
- //跳过前置的行数
- if (beginLine != 1) {
- while ((currentLine < (beginLine-1)) && br.readLine() != null) {
- ++currentLine;
- }
- }
-
- while ((tempStr = br.readLine()) != null && currentLine++ < endLine) {
- tempArray = tempStr.split("\t");
- tempObjectActionDetailVO = new ObjectActionDetail();
- tempObjectActionDetailVO.setIp(tempArray[0]);
- tempObjectActionDetailVO.setActionTime(sdf.parse(tempArray[1]));
- tempObjectActionDetailVO.setSrcObjTypeId(Integer.parseInt(tempArray[2]));
- tempObjectActionDetailVO.setSrcObjId(Integer.parseInt(tempArray[3]));
- tempObjectActionDetailVO.setTarObjTypeId(Integer.parseInt(tempArray[4]));
- tempObjectActionDetailVO.setTarObjId(Integer.parseInt(tempArray[5]));
- tempObjectActionDetailVO.setActionId(Integer.parseInt(tempArray[6]));
-
- tempObjectActionDetailVO.setScore(0);
- tempObjectActionDetailVO.setStatus(1);
-
- resultList.add(tempObjectActionDetailVO);
- }
-
- logger.info("Thread:" +
Thread.currentThread().getName() + " beginLine=" + beginLine + "
endLine=" + endLine);
-
- objectActionDetailService.insertObjectActionDetailBatch(resultList);
- } catch (FileNotFoundException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- } catch (IOException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- } catch (ParseException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- } finally {
- if (br != null) {
- try {
- br.close();
- br = null;
- } catch (IOException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- }
- }
-
- if (fr != null) {
- try {
- fr.close();
- fr = null;
- } catch (IOException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- }
- }
- }
- }
- }
- }
今天又试验了一下先将整个文件拆分成小的单个文件,然后每个线程再解析自己的文件。测试后感觉这样的效果不好,明显不如多线程从一个文章读数据好,27分钟插入了100W条数据,平均一分钟3.7W条左右。怀疑是多线程读取文件,本地磁盘的I/O受限导致性能低下。 代码如下:
- /**
- * 分析Apache日志的定时任务.每天运行数次.
- *
- * @author <a href="mailto:HL_Qu@hotmail.com">Along</a>
- *
- * @version $Revision$
- *
- * @since 2009-2-9
- */
- public class ApacheLogAnalysisTask {
- /**
- * Logger for this class
- */
- private static final Log logger = LogFactory.getLog(ApacheLogAnalysisTask.class);
-
- //总线程数
- private static final int THREAD_COUNT = 10;
-
- //每个线程插入的日志数
- private static final long LOG_COUNT_PER_THREAD = 3000;
-
- //日志文件的位置
- private static final String LOG_FILE = Property.LOG_FILE_PATH + "/formatLog.txt";
-
- private IObjectActionDetailService objectActionDetailService;
-
- public void setObjectActionDetailService(IObjectActionDetailService objectActionDetailService) {
- this.objectActionDetailService = objectActionDetailService;
- }
- public void execute() {
- this.multiAnalysisLog();
- }
-
- private void multiAnalysisLog() {
- ExecutorService exePool = Executors.newFixedThreadPool(THREAD_COUNT);
-
- FileReader fr = null;
- FileWriter fw = null;
- BufferedReader br = null;
- int threadCount = 0;
- long tempLineCount = 0;
- String tempReadLineStr = null;
- long now = System.currentTimeMillis();
- String logFileBackFile = Property.LOG_FILE_PATH
+ "/old/formatLog_" + DateUtil.getSystemCurrentDate() + "_" + now +
".txt";
- String logFilePerThreadName =
Property.LOG_FILE_PATH + "/old/formatLog_" +
DateUtil.getSystemCurrentDate() + "_" + now;
-
- try {
- //文件拷贝出来一个新的,并将原先的删除.
- FileUtil.copyfile(LOG_FILE, logFileBackFile, true);
- //FileUtil.deleteFile(LOG_FILE);
-
- fr = new FileReader(logFileBackFile);
- br = new BufferedReader(fr);
- fw = new FileWriter(logFilePerThreadName + "_" + ++threadCount + ".txt");
-
- while ((tempReadLineStr = br.readLine()) != null){
- tempLineCount++;
- fw.append(tempReadLineStr).append("\r\n");
-
- //每个线程分配固定的行数
- if(tempLineCount == LOG_COUNT_PER_THREAD) {
- fw.flush();
- fw.close();
- exePool.execute(new AnalysisLogTask(logFilePerThreadName + "_" + threadCount + ".txt"));
- //创建新的文件,临时变量清零.
- fw = new FileWriter(logFilePerThreadName + "_" + ++threadCount + ".txt");
- tempLineCount = 0;
- }
- }
-
- //最后一个线程有文件则写入执行,没有,则删除最后一个建立的文件.
- if (tempLineCount != 0) {
- fw.flush();
- fw.close();
- exePool.execute(new AnalysisLogTask(logFilePerThreadName + "_" + threadCount + ".txt"));
- } else {
- fw.flush();
- fw.close();
-
- FileUtil.deleteFile(logFilePerThreadName + "_" + threadCount + ".txt");
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (br != null) {
- try {
- br.close();
- br = null;
- } catch (IOException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- }
- }
-
- if (fr != null) {
- try {
- fr.close();
- fr = null;
- } catch (IOException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- }
- }
-
- FileUtil.deleteFile(logFileBackFile);
- logger.info("File has deleted:" + logFileBackFile);
-
- exePool.shutdown();
- //判断是不是所有的任务都执行完毕,执行完删除日志文件.
- while (true) {
- if (exePool.isTerminated()) {
- logger.info("All task has shutdown.");
- break;
- }
- }
-
- }
- }
-
- private class AnalysisLogTask implements Runnable {
- //每个线程要处理的日志文件
- private String logFilePath;
- public AnalysisLogTask(String logFilePath) {
- super();
- this.logFilePath = logFilePath;
- }
- @Override
- public void run() {
- logger.info("Thread:" + Thread.currentThread().getName() + " running.");
-
- FileReader fr = null;
- BufferedReader br = null;
- String tempStr = null;
- String[] tempArray = null;
- List <ObjectActionDetail> resultList = new ArrayList<ObjectActionDetail>();
-
- ObjectActionDetail tempObjectActionDetailVO = null;
- try {
- fr = new FileReader(logFilePath);
- br = new BufferedReader(fr);
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
- while ((tempStr = br.readLine()) != null) {
- tempArray = tempStr.split("\t");
- tempObjectActionDetailVO = new ObjectActionDetail();
- tempObjectActionDetailVO.setIp(tempArray[0]);
- tempObjectActionDetailVO.setActionTime(sdf.parse(tempArray[1]));
- tempObjectActionDetailVO.setSrcObjTypeId(Integer.parseInt(tempArray[2]));
- tempObjectActionDetailVO.setSrcObjId(Integer.parseInt(tempArray[3]));
- tempObjectActionDetailVO.setTarObjTypeId(Integer.parseInt(tempArray[4]));
- tempObjectActionDetailVO.setTarObjId(Integer.parseInt(tempArray[5]));
- tempObjectActionDetailVO.setActionId(Integer.parseInt(tempArray[6]));
-
- tempObjectActionDetailVO.setScore(0);
- tempObjectActionDetailVO.setStatus(1);
-
- resultList.add(tempObjectActionDetailVO);
- }
- objectActionDetailService.insertObjectActionDetailBatch(resultList);
- } catch (FileNotFoundException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- } catch (IOException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- } catch (ParseException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- } finally {
- if (br != null) {
- try {
- br.close();
- br = null;
- } catch (IOException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- }
- }
-
- if (fr != null) {
- try {
- fr.close();
- fr = null;
- } catch (IOException e) {
- if (logger.isErrorEnabled()) {
- logger.error("run()", e);
- }
- e.printStackTrace();
- }
- }
-
- //删除本线程负责的日志文件
- FileUtil.deleteFile(logFilePath);
- logger.info("Thread:" +
Thread.currentThread().getName() + " logFilePath has deleted:" +
logFilePath);
- logger.info("Thread:" + Thread.currentThread().getName() + " shutdown.");
- }
- }
- }
- }
后来又找系统管理员优化了一下网络,现在数据入库的速度是100W条7分钟 。相信应用和数据库移动到生产环境中,性能会进一步提升。
发表评论
-
One of the two will be used. Which one is undefined.
2019-04-22 23:13 596Mac版IntelliJ IDEA Class JavaLa ... -
Eclipse不提示的解决办法
2012-11-20 11:40 1291我们知道,在Eclipse中可 ... -
Hibernate-Validation的使用
2012-03-18 11:56 1458以前弄过hibernate-validation的,可今天 ... -
web.xml配置错误页面不起作用
2010-12-15 00:08 1077出现异常时没有进入到 common/500.jsp 页面 ... -
struts2 :Unable to load configuration. ……struts-default.xml:46:178异常解
2010-12-08 09:38 1131这个问题是缺 ... -
jsp中EL表达式不能显示的解决方法
2010-12-04 23:23 2415网友一:jsp中EL表达式 ... -
FreeMark常用内置函数使用说明
2010-11-27 11:59 889在我们应用Freemarker过程中,经常会操作例如字符串,数 ... -
lucene 排序
2010-11-18 18:42 959Lucene的默认排序是按照D ... -
设置tomcat内存
2010-11-02 10:21 1283设置tomcat内存 大家都 ... -
没有启动服务器服务,此时尚未创建共享资源的解决方法是什么
2010-11-01 10:57 1748方法一: 在桌面=>>我的电脑=>> ... -
struts2+displaytag翻页时Inappropriate OGNL expression解决方案(solution)
2010-10-23 11:21 1490相信肯定有人遇到这个问题: struts2+displa ... -
Tomcat性能参数
2010-10-21 23:40 1263maxThreads:Tomcat能处理的最大请求数(To ... -
JSTL操作Map
2010-10-21 23:38 23821、迭代 当forEach 的items属性中的 ... -
Quartz的cron表达式
2010-10-21 23:37 839一个cron表达式有至少6 ... -
IBatis的缓存
2010-10-21 23:31 918在xml配置文件中,每一个 cacheModel 元素,如下 ... -
Hibernate中get和load方法的区别
2010-10-21 23:27 766Hibernate3.2 Session加载数据时get和lo ... -
java的堆与栈的区别
2010-10-21 23:27 735Java的堆是一个运行时数据区,类的对象从中分配空间 。这些对 ... -
IBatis和Spring结合时的Blob乱码处理
2010-10-21 23:24 1585按照网上说的Spring和IBatis结合的时候要用以下配置进 ... -
【转】InnoDB锁定模式
2010-10-21 23:15 1045InnoDB实现标准行级锁定 ... -
经典SQL语句集锦
2010-10-18 20:40 884转自: http://blog.csdn.net/shixin ...
相关推荐
通过Druid的监控和多线程支持,可以有效优化系统性能,提高数据处理效率。 总结起来,这个项目展示了如何利用Spring Boot和Druid实现多数据源切换,以及如何在Spring Boot中配置和使用多线程来提升数据库操作的并发...
示例代码中使用了JDBC(Java Database Connectivity)API来建立与Oracle数据库的连接,并通过`DriverManager.getConnection()`方法获取连接。由于数据库连接是一种昂贵的资源,应避免在每个线程中重复创建连接,通常...
2. **Oracle数据库操作**:一旦建立了连接,我们可以通过`Statement`或`PreparedStatement`对象来执行SQL语句,包括查询、插入、更新和删除数据。在本示例中,还涉及到调用Oracle数据库中的函数和存储过程,这通常...
综上所述,Oracle数据库性能优化是一个复杂而细致的过程,需要综合考虑查询的特点、数据的结构以及系统的配置等多个因素。通过遵循上述原则和技巧,可以有效提升Oracle数据库的查询性能和整体运行效率。
Oracle数据库是全球广泛使用的大型关系型数据库管理系统,适用于处理大量数据和并发事务。 Oracle数据库连接模块的核心在于如何建立和管理与Oracle服务器的通信。在这个模块中,通常会用到Oracle的数据访问接口,如...
- 多线程:利用多线程并发处理不同部分的数据,提高导入速度。但是要注意数据库连接和事务管理的同步问题。 -流式解析:如使用Jackson的`JsonParser`,可以在解析过程中处理数据,减少内存占用。 5. 数据映射与...
此外,对于大型数据集,可能还需要考虑多线程处理、分批导入等优化策略,以减少内存占用和提高导入速度。同时,确保数据导入的事务一致性也是很重要的,特别是在数据校验失败或网络问题时,能够回滚已导入的部分。 ...
在C#.NET中批量插入大量数据到数据库是一个常见的任务,特别是在处理诸如从Excel文件导入数据等场景时。这里,我们将探讨如何使用C#.NET高效地完成这个任务,并提供一个简单的示例来说明整个过程。 首先,我们需要...
同时,根据数据量大小,可以考虑是否采用多线程并行处理。 8. **扩展性**:描述中提到代码有很好的扩展性,意味着可能设计了灵活的接口或抽象类,方便添加新的数据处理逻辑,比如支持其他类型的数据库,或者增加...
在Java Web开发中,连接Oracle数据库是一项常见的任务,它涉及到多层架构中的数据访问层(DAO,Data Access Object)设计,以及JDBC(Java Database Connectivity)技术的应用。本工程主要展示了如何通过Java代码与...
对于Oracle数据库,我们可以使用PL/SQL语句或者Oracle的SQL*Plus工具来实现。在SQL Server中,我们可以利用T-SQL语言进行数据检索。 接下来是数据转换,这个阶段的目标是将从源数据库抽取的数据转化为目标数据库...
通过上述步骤,开发者可以在Java应用中高效地使用Hibernate与Oracle数据库进行数据操作。实践过程中,应不断优化和调整,以适应不同场景的需求。在实际项目中,还需要关注性能监控、异常处理、安全防护等方面,确保...
在这个"socket大数据并行接收存数据库小例子"中,我们主要探讨的是如何利用Socket来处理大数据,并通过多线程技术提高数据处理的效率,最终将接收到的数据存储到数据库中。 首先,Socket是TCP/IP协议栈中的一个接口...
总的来说,这个Windows环境下的Oracle数据库查询工具提供了一个友好且功能丰富的界面,以帮助用户更方便地执行SQLPlus脚本,同时提供了多线程支持以及变量和参数功能,提升了工作效率。对于Oracle数据库的日常管理和...
源码通常包含主程序类、爬虫类、数据处理类和数据库连接类等,通过阅读源码可以学习到如何构建多线程爬虫,以及如何将抓取到的数据有效地存储到Oracle数据库中。 总结来说,这个项目提供了关于Java多线程爬虫技术和...
在实际应用中,可能还需要考虑错误处理、多线程安全、资源管理等细节。例如,当数据库连接失败时,程序应有适当的异常处理机制;对于并发访问,应保证印章操作的互斥性,防止多个用户同时修改同一份文档。 总的来说...
5. **数据复制**:获取到数据后,你需要将它们插入到目标数据库。同样,使用`PreparedStatement`可以执行INSERT语句。注意处理可能出现的并发问题,比如确保数据的一致性和避免重复插入。 6. **异常处理和日志记录*...
Oracle数据库在设计和管理大型数据系统时扮演着关键角色,其中序列(Sequence)是一种非常重要的对象,用于生成唯一的整数序列,通常用作表的主键。本篇将深入探讨Oracle数据库表序列ID自增生成器及其相关知识点。 ...
此外,它设计了针对内存优化的数据存储结构和算法,同时支持多进程或多线程共享数据存储,可以是嵌入式部署,也可以采用客户机-服务器模式。 TimesTen的性能表现非常出色,例如,它可以实现每秒数十万次的事务处理...
综上所述,VC++连接Oracle数据库涉及到环境配置、库的引用、数据库连接、SQL执行、结果处理等多个步骤。理解并熟练掌握这些知识点是开发高效稳定数据库应用程序的关键。在实际开发中,你可能还需要考虑线程安全、...