我的問題與如何做某事無關,它更多的是如何幫助提高性能。我爲這篇較長的文章道歉,但我認爲這是關於表演,我應該發佈所有關於我在做什麼的細節,看看有沒有人可以幫忙。使用BLOB獲得更好的性能,在JAVA上
我必須做一個程序,從2個不同的數據庫獲取信息,創建一個元數據,其相應的BLOB(pdf文件)並將其壓縮。
只有在數據庫中找到BLOB對象時纔會創建元數據文件。我設法這樣做了,但問題有時我可能會在查詢中得到高達80k的結果,並且可能需要長達20小時才能這樣做,考慮到每個blob對象不超過100 KB,這是荒謬的。
我有一個交易數據庫(讓我們稱之爲TEQ8P),其中存儲了元數據的所有ID和信息。我查詢的日期和狀態的數據(這很爛,但我沒有任何其他的過濾器,這是要求)
TEQ8P.openConnection();
Boolean flag = TEQ8P.ExecuteQuery("select tr.legaltransnumber, cc.country_code, tr.transnumber, tr.postingdate, tr.transdate from EQUATE.transheader tr inner join companycode_country cc on tr.tocompanycode = cc.company_code where tr.transtype = 'IC' and tr.transdate between to_date(" + date + ", 'DD/MM/YYYY') and to_date(" + nextday + ", 'DD/MM /YYYY')");
public Boolean ExecuteQuery(String query) {
Statement stmt;
ResultSet rs = null;
try {
stmt = connection.createStatement();
rs = stmt.executeQuery(query);
if(!rs.isBeforeFirst())
return false;
rowset = new CachedRowSetImpl();
rowset.populate(rs);
metadata = rs.getMetaData();
rs.close();
stmt.close();
return true;
} catch (SQLException e) {
HLog.error(e.getMessage());
e.printStackTrace();
return false;
//System.out.println(query);
}
finally
{
closeConnection();
}
}
我(再次按要求)使用JAVA 1.5,所以我下載了cachedrowsetimp從罐子oracle,所以一旦我完成查詢數據,我將它保存到內存並關閉連接。
之後,我開始瀏覽cachedrowset並查詢倉庫數據庫中的每個ID。我不能做一個選擇「在哪裏」,因爲沒有辦法知道是否會找到所有的id,並且「in」只會返回找到的項目,我不知道它沒有的項目找。但是,如果您有任何建議,請!
因此,我使用preparedStatement在ORACLE上使用綁定變量並開始編寫blob對象。
我的第一個問題,有沒有更好的方式來編寫blob文件?更快的方式?
if(flag)
{
String Query = "select wh.transnumber, wh.image from EQUATEWH.legalimage wh where wh.transnumber = ?";
WEQ8I.openConnection();
WEQ8I.setPreparedStmt(Query);
WEQ8I.WriteBlobs(PDF, TEQ8P.getRowsSet(), IC_FILE);
WEQ8I.closePrepStmt();
WEQ8I.closeConnection();
FileUtils.createZip(prop.getProperty("ZIPDIR_IC"), lsize, prop.getProperty("ZIPNAME_IC"));
public void WriteBlobs(String path, CachedRowSetImpl set, IMP_File IC_FILE)
{
ResultSet rs = null;
try
{
while(set.next())
{
pstmt.setString(1, set.getString(3));
rs = pstmt.executeQuery();
if(!rs.isBeforeFirst())
{
System.out.println("invoice " + set.getString(3) + "was not found on W database");
ErrorFile.writeErrorFile(set.getString(3));
}
else
{
//getting the name of the PDF file, if no ID use legaltransnumber
String ID = set.getString(1);
if(ID == null)
{
ID = set.getString(3);
}
while(rs.next())
{
FileOutputStream fos = null;
try
{
Blob blob = rs.getBlob(2);
InputStream is = blob.getBinaryStream();
fos = new FileOutputStream(path + ID + ".pdf");
int i = 0;
while ((i = is.read()) != -1)
{
fos.write(i);
}
fos.close();
is.close();
IC_FILE.fillIMPFile("IC", ID, set.getString(3), set.getString(2), set.getString(5));
}catch (Exception e)
{
e.printStackTrace();
ErrorFile.writeErrorFile(set.getString(3));
}
}
}
rs.close();
}
IC_FILE.writeFile();
} catch (SQLException e)
{
System.out.println("Problem when trying to create Record: " + path);
HLog.error(e.getMessage());
e.printStackTrace();
try
{
ErrorFile.writeErrorFile(set.getString(3));
}catch (Exception ex)
{
ex.printStackTrace();
HLog.error(e.getMessage());
}
}
}
如果查詢發現在WarehouseDB該ID的結果和圖像不爲空(這意味着它不會去零除外),我創建了metadafile這是IC_FILE。 IC_FILE不會寫入文件,它會將所有內容保存到內存中,當它寫完文件時,我認爲這可以幫助提高性能,因爲它不需要對每個文件執行I/O操作,只需要一次IC_FILE.writefile()。
要創建元數據文件,我還必須(根據要求再次)從文件中獲取容器名稱。要檢索容器名稱,我必須使用Transactional數據庫中的3個字段,將它們連接起來並在該文件中搜索它們。 這是我如何創建IMP文件,首先從每個記錄獲得的數據:
public void fillIMPFile(String type, String ID, String ID2, String companyCode, String date)
{
date = date.substring(0, 10);
date = date.replace("-", "/");
date = date.substring(5, 7) + "/" + date.substring(8, 10) + "/" + date.substring(0, 4);
String Name = prop.getProperty("NAME");
String info = prop.getProperty(type);
String DOS = Name + info + ID + ".";
String NOTES = Name + " " + info + " ";
info += getContainer(companyCode, date, type);
if(type.equals("IC"))
{
String desc = prop.getProperty("DESC_PDF");
DOS += "pdf";
NOTES += desc + " " + ID + " " + ID2;
buffer += info + "\t" + date + "\t" + date + "\t" + DOS + "\t" + NOTES + "\t"
+ NOTES + "\t" + ID2;
}
得到我使用對象的屬性的容器,但我想有可能是更好的選擇?哈希圖可能?
public String getContainer(String companyCode, String Date, String type)
{
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
Date = sdf.format(cal.getTime());
//mal siempre pondra 2012
String data = type + companyCode + Date;
String container = containers.getProperty(data);
if(container == null)
{
data = type + "WW" + Date;
container = containers.getProperty(data);
}
return container;
}
finaly寫入文件:
public void writeFile()
{
try
{
FileWriter fw = new FileWriter(File, true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(buffer);
bw.close();
}catch (IOException e)
{
e.printStackTrace();
HLog.error(e.getMessage());
}
}
謝謝! 丹尼爾
忘了提,容器文件中有2700個容器名稱創建超過1個容器文件,所以它搜索一個一個:S –