sqllite数据库方式与系统方式访问大量小文件的速度对比
**背景**:项目中有许多小文件时,系统对小文件的访问开销较大,比较慢;此时尝试将小文件合并成大文件,并将每个小文件的索引信息(比如起始位置与结束位置)存入数据库中,通过数据库访问小文件可能能够减小时间开销。
使用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.*中的类表示。
上一篇: 线性表(数据结构学习笔记)
下一篇: 笔记,Vector类模板的基本功能