- 浏览: 507790 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (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 553Mac版IntelliJ IDEA Class JavaLa ... -
Eclipse不提示的解决办法
2012-11-20 11:40 1256我们知道,在Eclipse中可 ... -
Hibernate-Validation的使用
2012-03-18 11:56 1409以前弄过hibernate-validation的,可今天 ... -
web.xml配置错误页面不起作用
2010-12-15 00:08 1032出现异常时没有进入到 common/500.jsp 页面 ... -
struts2 :Unable to load configuration. ……struts-default.xml:46:178异常解
2010-12-08 09:38 1095这个问题是缺 ... -
jsp中EL表达式不能显示的解决方法
2010-12-04 23:23 2355网友一:jsp中EL表达式 ... -
FreeMark常用内置函数使用说明
2010-11-27 11:59 845在我们应用Freemarker过程中,经常会操作例如字符串,数 ... -
lucene 排序
2010-11-18 18:42 935Lucene的默认排序是按照D ... -
设置tomcat内存
2010-11-02 10:21 1255设置tomcat内存 大家都 ... -
没有启动服务器服务,此时尚未创建共享资源的解决方法是什么
2010-11-01 10:57 1711方法一: 在桌面=>>我的电脑=>> ... -
struts2+displaytag翻页时Inappropriate OGNL expression解决方案(solution)
2010-10-23 11:21 1439相信肯定有人遇到这个问题: struts2+displa ... -
Tomcat性能参数
2010-10-21 23:40 1214maxThreads:Tomcat能处理的最大请求数(To ... -
JSTL操作Map
2010-10-21 23:38 23391、迭代 当forEach 的items属性中的 ... -
Quartz的cron表达式
2010-10-21 23:37 795一个cron表达式有至少6 ... -
IBatis的缓存
2010-10-21 23:31 874在xml配置文件中,每一个 cacheModel 元素,如下 ... -
Hibernate中get和load方法的区别
2010-10-21 23:27 728Hibernate3.2 Session加载数据时get和lo ... -
java的堆与栈的区别
2010-10-21 23:27 700Java的堆是一个运行时数据区,类的对象从中分配空间 。这些对 ... -
IBatis和Spring结合时的Blob乱码处理
2010-10-21 23:24 1550按照网上说的Spring和IBatis结合的时候要用以下配置进 ... -
【转】InnoDB锁定模式
2010-10-21 23:15 1005InnoDB实现标准行级锁定 ... -
经典SQL语句集锦
2010-10-18 20:40 859转自: http://blog.csdn.net/shixin ...
相关推荐
一个基于Springboot的小项目,采用Druid多数据源的设计,可以同时操作Mysql与Oracle数据库,配置了多线程处理任务,为刚接触springboot的朋友提供参考。
4.4.3 具有历史数据的产品OLTP数据库 设计 71 4.4.4 数据仓库设计 72 4.5 文件位置 75 4.6 数据库空间使用概述 76 4.6.1 storage子句的意义 77 4.6.2 表段 78 4.6.3 索引段 79 4.6.4 回滚段 79 4.6.5 临时段 79 ...
java快速插入千万级数据,亲测91秒插入1700万数据!!!
在Oracle数据库中,数据库的操作模式分为专用服务器(DELICATED SERVER)模式和多线程服务器(MULTITHREADED SERVER)模式两种。其中,在专用服务器模式中为每个用户进程创建一个服务器进程,用户进程与服务器进程之间...
第8章ORACLE数据库系统优化安装 91 §7.1 应用系统环境规划和Oracle系统安装考虑 91 §7.1.1 操作系统安装考虑 91 §7.1.2 Oracle系统安装考虑 92 §7.2 关于创建多个Oracle实例问题 93 §7.3 Oracle系统安装后的...
多线程、多连接、智能/彩色SQL编辑器、中英文双语界面并能切换、支持 PL/SQL、批量SQL运行、高效的块操作、方便的表格操作,不需要安装 Oracle 客户端,能运行于所有的主流平台包括 Windows、Linux 、Unix 及 Mac ...
采用jdbc连接数据库,将两种不同类型的数据(SqlServer、Oracle)进行转换,来完成数据库数据的迁移。 实现方式,查询SqlServer数据,批处理插入到Oracle中。
常见的数据库系统有以下几种: MySQL MySQL是一个快速的、多线程、多用户和健壮的SQL数据库服务器。MySQL服务器支持 关键任务、重负载生产系统的使用,也可以将它嵌入到一个大配置(mass- deployed)的软件中去。 SQL...
片文章介绍了一个Java批量添加数据,多个字段同时添加多条数据具体实例,面向的是Oracle数据库,需要的朋友可以参考下
百度百科多线程爬虫Java源码,数据存储采用了Oracle11g 简介 采用了MyEclipes作为集成开发环境,应该是兼容的eclips 使用方法 下载此原始代码后使用(导入或导入)操作导入此项目 各个类介绍 HtmlDAO.java 主要是...
本工具是用 Java 开发的、专门用于 Oracle 数据库操作的一种图形界面工具: 多线程、多连接、支持 PL/SQL、功能实用、操作简便,能运行于所有平台包括 Windows、Linux 及 Unix,勿需安装 Oracle 客户端,仅 2.8 MB ...
常见数据库系统: MySQL MySQL是一个快速的、多线程、多用户和健壮的SQL数据库服务器。MySQL服务器支持关键任务、重负载生产系统的使用,也可以将它嵌入到一个大配置(mass- deployed)的软件中去。 SQL Server SQL ...
将 SELECT 语句的查询结果显示在工作表,可以直接对查询结果进行再操作,如 修改、插入行、删除行、提 交(将表格中的数据改变写入相应的数据库表中)、多功能拷贝、将选择的单元格数据导出为 XLS /CSV /INSERT SQL ...
将 SELECT 语句的查询结果显示在工作表,可以直接对查询结果进行再操作,如 修改、 插入行、删除行、提交(将表格中的数据改变写入相应的数据库表中)、多功能拷贝、将选 择的单元格数据导出为 XLS /CSV /INSERT SQL...
Oracle数据库有哪几种启动方式 说明: 有以下几种启动方式: 1、startup nomount 非安装启动,这种方式启动下可执行:重建控制文件、重建数据库 读取init.ora文件,启动instance,即启动SGA和后台进程,这种启动...
所有文件都是通过多线程过程创建和转换的,从而使其速度更快将所有sql存储在Folder AllSql中(在每次转换时生成并清理)必需的MariaDb 10x和更多NetCore3.1或更高导航(比插入sql更好的phpmyadmin)怎么做首先对您的...
# 如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多新的线程, # 增加这个值可以改善系统性能.通过比较Connections和Threads_created状态的变量,...
PL/SQL Developer是一个集成开发环境,专门面向Oracle数据库存储程序单元的开发。如今,有越来越多的商业逻辑和应用逻辑转向了Oracle Server,因此,PL/SQL编程也成了整个开发过程的一个重要组成部分。PL/SQL ...
PL/SQL Developer是一个集成开发环境,专门面向Oracle数据库存储程序单元的开发。如今,有越来越多的商业逻辑和应用逻辑转向了Oracle Server,因此,PL/SQL编程也成了整个开发过程的一个重要组成部分。PL/SQL ...