欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

sqllite数据库方式与系统方式访问大量小文件的速度对比

程序员文章站 2022-07-14 19:49:37
...
**背景**:项目中有许多小文件时,系统对小文件的访问开销较大,比较慢;此时尝试将小文件合并成大文件,并将每个小文件的索引信息(比如起始位置与结束位置)存入数据库中,通过数据库访问小文件可能能够减小时间开销。
使用sqllite数据库,在linux下装好数据库、java、相应的数据库jdbc的jar包,开始测试:
Step 1:将小文件合并成大文件,并将索引写入数据库中:
import java.sql.*;

import java.io.;
public class FileCombine
{
public static void main( String args[] )
{
Connection connection = null;
Statement stmt = null;
try {
Class.forName(“org.sqlite.JDBC”);
connection=DriverManager.getConnection(“jdbc:sqlite:test1.db”);
System.out.println(“是否成功连接pg数据库”+connection);
String FileOut="/home/jojo/sqllite/1.txt";//输出路径
BufferedWriter bw=new BufferedWriter(new FileWriter(FileOut));
//读取目录下的每个文件或者文件夹,并读取文件的内容写到目标文字中去
File[] list = new File("/mnt/shared/sample_data/data").listFiles();
//File[] list = new File("/home/jojo/hello/test").listFiles();
int fileCount = 0,location=0;
for(File file : list)
{
if(file.isFile())
{
stmt = connection.createStatement();
//System.out.println(file.getName());
fileCount++;
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
location++;
}
String sql = “INSERT INTO date (id,filename,file_index) VALUES(”+fileCount+",’"+file.getName()+"’,"+location+");";
stmt.executeUpdate(sql);
stmt.close();
br.close();
}
}
bw.close();
connection.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
}
}
Step 2:将小文件的文件名取出存在txt里,之后访问要用
import java.io.
;
public class Getname {

public static  void  main(String[] args) throws IOException {

 try {


    String FileOut="/home/jojo/name2.txt";

    BufferedWriter bw=new BufferedWriter(new FileWriter(FileOut));

  //读取目录下的每个文件或者文件夹,并读取文件的内容写到目标文字中去

    File[] list = new File("/mnt/shared/sample_data/data").listFiles();

  
    for(File file : list)

    {

        if(file.isFile())

        {
       	//System.out.println(file.getName());
            
          //  BufferedReader br = new BufferedReader(new FileReader(file));
            String line=file.getName();
	bw.write(line);
	bw.newLine();

        }

    }

    bw.close();


}catch (Exception e) {

        e.printStackTrace();

}

}

}
Step 3:测试系统直接访问时间(大致用file.exist()的时间代表,不知道有没有更好且简便的办法)和使用数据库访问的时间(用从数据库中取出索引的时间表示),测试点为100到10000间以100为步长、10000到1300000间以10000为步长,将测试结果写入database_data.txt、system_data.txt:
import java.io.;
import java.sql.
;
import java.util.Random;

public class Test {

public static  void  main(String[] args) throws IOException {
Connection connection = null;
    Statement stmt = null;
BufferedWriter bw1=new BufferedWriter(new FileWriter("system_data.txt"));
BufferedWriter bw2=new BufferedWriter(new FileWriter("database_data.txt"));
int FILENUM=1329182;
    int N=100 ;
 try {
 	Class.forName("org.postgresql.Driver");
	connection= DriverManager.getConnection("jdbc:sqlite:test1.db");
	System.out.println("是否成功连接pg数据库"+connection);
	Random r =new Random(System.currentTimeMillis());
 	while(N<FILENUM){

		String[] s=new String[N];
		File file = new File("name2.txt");//此文件存着小文件名
		
		FileReader fileReader = new FileReader(file);
		LineNumberReader reader = new LineNumberReader(fileReader);
		int k=0;
		for(int i=0;i<N;i++){
			int a = r.nextInt(FILENUM);
		//System.out.println(a);
			int line=0;
			while(true){
				if(a==line){
					s[k]=reader.readLine();
					k++;
					break;
				}
				line++;
			}
		}
		reader.close();
		fileReader.close();

//system test time
long timeStart = System.currentTimeMillis();
for(int j=0;j<N;j++){
File file1 = new File("/mnt/shared/sample_data/data/"+s[j]);
file1.exists();
//file1.close();
}
long timeEnd = System.currentTimeMillis();
//System.out.println(“fopen花费:” + (timeEnd - timeStart) + “ms”);
String line=String.valueOf(timeEnd - timeStart);
bw1.write(line);
bw1.newLine();
//database method test time
stmt = connection.createStatement();
timeStart = System.currentTimeMillis();

  		for(int idx=0;idx<N;idx++){ 
				//stmt.executeUpdate("SELECT index from merge_data where filename LIKE 'db151010.abj';");
			//System.out.println(s[idx]);
			stmt.executeQuery("select file_index from date where filename = '"+s[idx]+"';");
			//rs.next();
			//rs.getInt("index");							
			//int res=rs.getInt("index");
		}
		timeEnd = System.currentTimeMillis();
		stmt.close();
		line=String.valueOf(timeEnd - timeStart);
		bw2.write(line);
		bw2.newLine(); 
		if(N<10000){
			N+=100;
		}else{
			N+=10000;
		} 		
 	}

	//System.out.println("database 花费:" + (timeEnd - timeStart) + "ms");
	bw1.close();
	bw2.close();
}catch (Exception e) {
        e.printStackTrace();
}
}

}
总结:从结果来看,sqllite(建立了b_tree索引之后)要快于system,但这样的计时方式感觉还是有许多的误差及很多欠考虑的地方,并且系统找到文件的时间也可以优化,不用java.io.*中的类表示。