文件读写并发操作性能问题 数据库有400万记录,每条记录生成一个txt文件 就是生成400W个txt,基于多线程操作,会不会有性能瓶劲,如果有会是在什么地方 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 400 万个文件你怎么放哦,一个目录下所能包含的子目录或文件的个数是有限的,这 400 万个文件还得分成 N 个目录,N 个子目录的来存放,具体的需要规划一下。另外,采用多线程的方式做 IO 操作根本不会提高效率,因为硬盘的磁头只有一个!数据库操作也是 IO 操作,写文件也是 IO 操作,也就是说磁头是在满负荷下工作的。如果采用多线程的话也非常麻烦,让哪个线程去读取哪条记录,并写到哪个文件中去也需要做很好的设计。想不通为什么数据库中有的东西,还要再存成文件呢?如果数据库中的数据产生了变化,那么生成的这个文件得重新生成? 如果生成400w个文件(在同一个文件目录下,能不能生成就是个问题),据兄弟多年以前的经验,在一个目录下如果文件数量超过4w,哪怕每个文件都很小,图形界面如Windows上的文件浏览器就需要一个上午才能打开那个目录:),如果一个目录下超过10w个文件,那么这个目录就很危险了,要知道inode是有限的,目录下的文件数量也是有限的。建议你使用别的策略。 谢谢你的建议这个我知道,我说400W只是想说明数据量比较大,并不一定是400W,或者没有400W也或者多于400W 400百万个文件要存放 问题大了首先你这样window文件系统容易崩溃,建议使用其他文件系统 如果非要这么做从数据库中读和写文件最慢数据库读你没必要用线程数据库已经帮你做了你的瓶颈在与io损失.一般每秒20~30M的硬盘写入速度而你读数据没有这么快差一点应该不多 因此再多的线程也没用最多两线程一个读一个写,但是性能提高不大,又增加了复杂性设置缓存零散的写文件io损失很大,如10m 写一次,这样速度会快对硬盘也比较友好. 谢谢你的回复,实际用多线程分段对数据库读取很快而且快很多呵呵。代码已经写来了,问题在于写文件呵呵,FileWriter时总会产生FileNotFountException /** * Filename: MultiThread.java * Description: * 测试以多线程方式对数据库大数据进行分段读取,并以多线程式对每条记录生成文件 * 1.对数据库记录分段读取设每段5000条记录 * 2.设数据记录为10*5000 * 3.启动10个线程分别读取10段数据 * 4.运用observer 模式对DataTable对象进行监视 * 5.当DataTable 发生改变时通知写文件线程 * 6.写文件线程启动读文件 * * * Copyright: Copyright (c)2008 * Company: DAWNPRO INFORMATION & TECHNOLOGY TECHNOLOGY LIMITED COMPANY * @author: Cary Peng * @version: 1.0 * Create at: Apr 28, 2009 3:15:04 PM * * Modification History: * Date Author Version Description * ------------------------------------------------------------------ * Apr 28, 2009 Cary Peng 1.0 1.0 Version */package cn.com.eng;import java.io.FileInputStream;import java.io.FileWriter;import java.io.IOException;import java.io.InputStream;import java.util.Observable;import java.util.Observer;import java.util.Properties;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import javax.sql.DataSource;import com.dawnpro.data.core.ConnectionManager;import com.dawnpro.data.core.DataRow;import com.dawnpro.data.core.DataTable;import com.dawnpro.data.core.Executor;import com.dawnpro.data.core.Operation;import com.dawnpro.data.dsa.DataSourceFactory;import com.dawnpro.data.dsa.DataSourceProperties;import com.dawnpro.data.dsa.DataSourcePropertiesFactory;public class MultiThread { private static final int POOL_SIZE = 15; private static final String DBFILE_PATH = "db.properties"; private static final String QUERY_SQL = "select * from test limit "; private ExecutorService executorService = null; public MultiThread() { executorService = Executors.newFixedThreadPool(POOL_SIZE); } public void start() { int[] limit = new int[10]; int radix = 5000; // 构建limit列表,每次取5000条记录 for (int i = 0; i < limit.length; i++) { limit[i] = radix; radix = radix + 5000; } StringBuffer querySQL = new StringBuffer(QUERY_SQL); // 通过limit列表长度构 for (int idx = 0; idx < limit.length; idx++) { if (idx == 0) { querySQL.append(limit[idx]); } else { querySQL.append(limit[idx - 1]); querySQL.append(","); querySQL.append(limit[idx]); } executorService.execute(new ReadThread(querySQL.toString(), idx)); querySQL.delete(QUERY_SQL.length(), querySQL.length()); } } /**读数据线程 继续被观察者并实现Runnable接口 * @author Cary * 根据指定的SQL,读取数据库记录 * */ class ReadThread extends Observable implements Runnable { private String querySQL = null; private int taskid; private DataTable dataTable = null; public ReadThread(String sql, int id) { this.querySQL = sql; this.taskid = id; } //启动线程 读取数据 public void run() { System.err.println(Thread.currentThread().getName()); try { Executor executor = init(); Operation opt = null; opt = new Operation(querySQL); executor.executeSql(opt); setDataTable(executor.getResult()); } catch (Exception ex) { ex.printStackTrace(); } System.out.println("Current id of the task is :" + taskid + " exec sql :" + querySQL); } /**获取SQL 执行器 * @return Executor SQL执行器 */ private Executor init() { InputStream in = null; Executor exec = null; try { Properties prop = new Properties(); in = new FileInputStream(DBFILE_PATH); prop.load(in); DataSourceProperties dsProp = DataSourcePropertiesFactory .create(prop); DataSource ds = DataSourceFactory.getDataSource(dsProp); ConnectionManager connMgr = new ConnectionManager(ds); exec = new Executor(connMgr); } catch (Exception ex) { ex.printStackTrace(); } return exec; } public DataTable getDataTable() { return dataTable; } public void setDataTable(DataTable dataTable) { this.dataTable = dataTable; this.setChanged(); //datatable 发生改变通知写文件线程,注册观察者 this.addObserver(new FileWriteThread()); //发出通知 this.notifyObservers(dataTable); } } /**写文件线程 实现观察者接口 * @author Cary * */ class FileWriteThread implements Runnable, Observer { private DataTable dataTable = null; public void run() { writeFile(dataTable); } public FileWriteThread() { } private void writeFile(DataTable dataTbl) { FileWriter writer = null; for (int idx = 0; idx < dataTbl.getRowCount(); idx++) { DataRow row = dataTbl.getDataRow(idx); try { writer = new FileWriter("D:\\test\\" + idx + ".txt"); writer.write(row.toString()); writer.close(); } catch (IOException e) { System.out.println(e.getStackTrace()); e.printStackTrace(); } } } public void update(Observable o, Object arg) { if (arg instanceof DataTable) { this.setDataTable((DataTable) arg); writeFile(this.dataTable); } } public DataTable getDataTable() { return dataTable; } public void setDataTable(DataTable dataTable) { this.dataTable = dataTable; } } public static void main(String[] args) { new MultiThread().start(); }} 怎么会都认为从数据库读文件很慢呢呵呵!实际用多线程分段读很快,我是以5W来做测试的。。大了机器跑不到jvm内存指定到1024了一次性还OutOfMemonyException....分段多程基本没有出现这种情况 三星教你轻松入门手机软件开发,从贫民到富翁,一切都那么简单给大家推荐个从销售手机软件致富,并提供手机软件入门学习到开发指导,的“一条龙”服务的三星移动创新者园地:http://innovatorsamsungmobile.com/71简单说下我的推荐理由:1、3G催生更大规模的软件需求,三星用户达八千九百万,市场份额占第二位。在线商店,手机预装,帮你改进并推销软件,一周挣两万成为可能。2、网站教你如何搭建开发环境,全中文安装环境,让你即刻轻松入手。3、丰富的入门者学习资料(教程、实例),教你如何写出第一个程序,不用到处搜索资料。4、专业手机软件工程师回答你的学习开发问题,快速有水准。刚在三星的网站上看到一条消息,苏州的一个朋友已编写出自己的手机软件,已放在三星官方网络商店,两周内的下载量超过3000次,分成有30%。希望朋友们都能借此良机掏到自己的第一桶金。 观察中的update方法是线程安全性的为什么writerFile会出现FileNotFoundException 求大神给小弟盖盖码字,实在是改不动了... java多线程更新时的问题,请大牛解释。 java awt swing问题 一个处理字符串的小问题 字符串转换为时间 请问不使用Jdbc,且不下载任务驱动。,是否可以直接用Jsp链接Access 程序员轻松一刻。聊聊 高分请教,关于多线程,十分的奇怪!!! javamail问题?? 如何用JAVA程序取得UNIX机器下的当前用户? 求救!JDialog的一个小程序编译通不过 请问各位师兄,这堆错什么意思啊?
这 400 万个文件还得分成 N 个目录,N 个子目录的来存放,具体的需要规划一下。另外,采用多线程的方式做 IO 操作根本不会提高效率,因为硬盘的磁头只有一个!数据库操作也是 IO 操作,写文件也是 IO 操作,也就是说磁头是在满负荷下工作的。如果采用多线程的话也非常麻烦,让哪个线程去读取哪条记录,并写到哪个文件中去
也需要做很好的设计。想不通为什么数据库中有的东西,还要再存成文件呢?如果数据库中的数据产生了变
化,那么生成的这个文件得重新生成?
首先你这样window文件系统容易崩溃,建议使用其他文件系统
如果非要这么做从数据库中读和写文件最慢数据库读你没必要用线程数据库已经帮你做了你的瓶颈在与io损失.一般每秒20~30M的硬盘写入速度而你读数据没有这么快差一点应该不多 因此再多的线程也没用
最多两线程一个读一个写,但是性能提高不大,又增加了复杂性
设置缓存零散的写文件io损失很大,如10m 写一次,这样速度会快对硬盘也比较友好.
谢谢你的回复,实际用多线程分段对数据库读取很快而且快很多呵呵。代码已经写来了,问题在于写文件呵呵,
FileWriter时总会产生FileNotFountException
* Filename: MultiThread.java
* Description:
* 测试以多线程方式对数据库大数据进行分段读取,并以多线程式对每条记录生成文件
* 1.对数据库记录分段读取设每段5000条记录
* 2.设数据记录为10*5000
* 3.启动10个线程分别读取10段数据
* 4.运用observer 模式对DataTable对象进行监视
* 5.当DataTable 发生改变时通知写文件线程
* 6.写文件线程启动读文件
*
*
* Copyright: Copyright (c)2008
* Company: DAWNPRO INFORMATION & TECHNOLOGY TECHNOLOGY LIMITED COMPANY
* @author: Cary Peng
* @version: 1.0
* Create at: Apr 28, 2009 3:15:04 PM
*
* Modification History:
* Date Author Version Description
* ------------------------------------------------------------------
* Apr 28, 2009 Cary Peng 1.0 1.0 Version
*/
package cn.com.eng;import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.Observable;
import java.util.Observer;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import javax.sql.DataSource;import com.dawnpro.data.core.ConnectionManager;
import com.dawnpro.data.core.DataRow;
import com.dawnpro.data.core.DataTable;
import com.dawnpro.data.core.Executor;
import com.dawnpro.data.core.Operation;
import com.dawnpro.data.dsa.DataSourceFactory;
import com.dawnpro.data.dsa.DataSourceProperties;
import com.dawnpro.data.dsa.DataSourcePropertiesFactory;public class MultiThread { private static final int POOL_SIZE = 15;
private static final String DBFILE_PATH = "db.properties";
private static final String QUERY_SQL = "select * from test limit ";
private ExecutorService executorService = null; public MultiThread() {
executorService = Executors.newFixedThreadPool(POOL_SIZE);
} public void start() {
int[] limit = new int[10];
int radix = 5000;
// 构建limit列表,每次取5000条记录
for (int i = 0; i < limit.length; i++) {
limit[i] = radix;
radix = radix + 5000;
}
StringBuffer querySQL = new StringBuffer(QUERY_SQL);
// 通过limit列表长度构
for (int idx = 0; idx < limit.length; idx++) {
if (idx == 0) {
querySQL.append(limit[idx]);
} else {
querySQL.append(limit[idx - 1]);
querySQL.append(",");
querySQL.append(limit[idx]);
}
executorService.execute(new ReadThread(querySQL.toString(), idx));
querySQL.delete(QUERY_SQL.length(), querySQL.length());
}
} /**读数据线程 继续被观察者并实现Runnable接口
* @author Cary
* 根据指定的SQL,读取数据库记录
*
*/
class ReadThread extends Observable implements Runnable {
private String querySQL = null;
private int taskid;
private DataTable dataTable = null; public ReadThread(String sql, int id) {
this.querySQL = sql;
this.taskid = id;
}
//启动线程 读取数据
public void run() {
System.err.println(Thread.currentThread().getName());
try {
Executor executor = init();
Operation opt = null;
opt = new Operation(querySQL);
executor.executeSql(opt);
setDataTable(executor.getResult()); } catch (Exception ex) {
ex.printStackTrace();
}
System.out.println("Current id of the task is :" + taskid
+ " exec sql :" + querySQL); }
/**获取SQL 执行器
* @return Executor SQL执行器
*/
private Executor init() {
InputStream in = null;
Executor exec = null;
try {
Properties prop = new Properties();
in = new FileInputStream(DBFILE_PATH);
prop.load(in);
DataSourceProperties dsProp = DataSourcePropertiesFactory
.create(prop);
DataSource ds = DataSourceFactory.getDataSource(dsProp);
ConnectionManager connMgr = new ConnectionManager(ds);
exec = new Executor(connMgr);
} catch (Exception ex) {
ex.printStackTrace();
}
return exec;
} public DataTable getDataTable() {
return dataTable;
} public void setDataTable(DataTable dataTable) {
this.dataTable = dataTable;
this.setChanged();
//datatable 发生改变通知写文件线程,注册观察者
this.addObserver(new FileWriteThread());
//发出通知
this.notifyObservers(dataTable);
} } /**写文件线程 实现观察者接口
* @author Cary
*
*/
class FileWriteThread implements Runnable, Observer { private DataTable dataTable = null; public void run() {
writeFile(dataTable);
} public FileWriteThread() {
} private void writeFile(DataTable dataTbl) {
FileWriter writer = null; for (int idx = 0; idx < dataTbl.getRowCount(); idx++) {
DataRow row = dataTbl.getDataRow(idx);
try {
writer = new FileWriter("D:\\test\\" + idx + ".txt");
writer.write(row.toString());
writer.close();
} catch (IOException e) {
System.out.println(e.getStackTrace());
e.printStackTrace();
}
}
} public void update(Observable o, Object arg) {
if (arg instanceof DataTable) {
this.setDataTable((DataTable) arg);
writeFile(this.dataTable);
} } public DataTable getDataTable() {
return dataTable;
} public void setDataTable(DataTable dataTable) {
this.dataTable = dataTable;
}
} public static void main(String[] args) {
new MultiThread().start();
}}
给大家推荐个从销售手机软件致富,并提供手机软件入门学习到开发指导,的“一条龙”服务的三星移动创新者园地:http://innovatorsamsungmobile.com/71
简单说下我的推荐理由:
1、3G催生更大规模的软件需求,三星用户达八千九百万,市场份额占第二位。在线商店,手机预装,帮你改进并推销软件,一周挣两万成为可能。
2、网站教你如何搭建开发环境,全中文安装环境,让你即刻轻松入手。
3、丰富的入门者学习资料(教程、实例),教你如何写出第一个程序,不用到处搜索资料。
4、专业手机软件工程师回答你的学习开发问题,快速有水准。
刚在三星的网站上看到一条消息,苏州的一个朋友已编写出自己的手机软件,已放在三星官方网络商店,两周内的下载量超过3000次,分成有30%。希望朋友们都能借此良机掏到自己的第一桶金。