Ich muss eine Tabellenkalkulationsdatei in Java abfragen. Ich verwende Apache MetaModel.Apache MetaModel - schlechte Performance-Abfrage Tabellenkalkulation
ich importiert es mit Maven mit
<dependency>
<groupId>org.apache.metamodel</groupId>
<artifactId>MetaModel-excel</artifactId>
<version>4.5.2</version>
</dependency>
Alles funktioniert gut, aber die next()
Anweisung, wenn es falsch ein paar Sekunden dauert zurück soll, warum?
import org.apache.metamodel.DataContext;
import org.apache.metamodel.excel.ExcelDataContext;
import org.apache.metamodel.schema.Schema;
import org.apache.metamodel.schema.Column;
import org.apache.metamodel.schema.Table;
import org.apache.metamodel.query.Query;
import org.apache.metamodel.query.OperatorType;
import org.apache.metamodel.data.DataSet;
import org.apache.metamodel.data.Row;
import org.apache.metamodel.MetaModelException;
public class SpreadsheetReader {
private File spreadsheet;
public SpreadsheetReader(String spreadsheetLocation, String spreadsheetName){
this.spreadsheet = new File(spreadsheetLocation + spreadsheetName);
if(!"OK".equals(checkSpreadSheet())){
throw new IllegalStateException("Error in spreadsheet. Cause: "+spreadsheetStatus);
}
}
/** query the excel spreadsheet for the given ID
*/
public List<String> query(String givenProgId){
List<String> linksArray = new ArrayList<String>();
int rowCount = 0;
ExcelConfiguration conf = new ExcelConfiguration(1, true, true); // columnNameLineNumber, skipEmptyLines, sEColumns
DataContext dataContext = new ExcelDataContext(this.spreadsheet, conf);
System.out.println("PROFILING >>> "+(new org.joda.time.DateTime())+" START-1"); // ##
Schema schema = dataContext.getDefaultSchema();
System.out.println("PROFILING >>> "+(new org.joda.time.DateTime())+" STOP-1"); // ##
// Takes 2 seconds. Will be moved into constructor.
Table table = schema.getTables()[0];
Column idsColumn = table.getColumnByName("ProgID");
Column titlesColumn = table.getColumnByName("Titles");
Query query = new Query().select(titlesColumn)
.from(table)
.where(idsColumn, OperatorType.EQUALS_TO, givenProgId);
try(DataSet dataSet = dataContext.executeQuery(query)){ // try-with-resource, no need to close dataset
while (dataSet.next()) {
// the rows are read quite quickly, problem will be when next() is false
++rowCount;
Row currentRow = dataSet.getRow();
String currentTitle = (String)currentRow.getValue(0);
linksArray.add("my-service/titles/"+currentTitle);
System.out.println("PROFILING >>> "+(new org.joda.time.DateTime())+" START-2"); // @@@@@@@
}
System.out.println("PROFILING >>> "+(new org.joda.time.DateTime())+" STOP-2"); // @@@@@@@
// TAKES ABOUT 6 SECONDS - (Excel file has just 14.779 rows and 114 columns)
}catch(MetaModelException xx){
//logger
throw xx;
}
return linksArray;
}
}}
UPDATE: Einige weitere Profilierung mit einem Tabellenkalkulationsdokument mit nur 3 Einträge:
-Code ist jetzt:
try(DataSet dataSet = this.dataContext.executeQuery(query)){
// FIRST NEXT() with result => quite fast
System.out.println("\n PROFILING >>> "+(new org.joda.time.DateTime())+" START a\n");
System.out.println("\n 88888 NEXT >>> "+(dataSet.next())+" <<<< \n");
Row currentRow = dataSet.getRow();
String currentTitle = (String)currentRow.getValue(0);
System.out.println("\n READ: "+(new org.joda.time.DateTime())+" >>> "+currentTitle+" \n");
System.out.println("\n PROFILING >>> "+(new org.joda.time.DateTime())+" STOP a\n");
// SECOND AND LAST NEXT() => very SLOW
System.out.println("\n PROFILING >>> "+(new org.joda.time.DateTime())+" START b\n");
System.out.println("\n 88888 NEXT >>> "+(dataSet.next())+" <<<< \n");
System.out.println("\n PROFILING >>> "+(new org.joda.time.DateTime())+" STOP b\n");
}
Und die Tabelle in der vorbelastete ist Klassenkonstruktor.
Logs (mit Zeiten) für die letzte einer Reihe von nachfolgenden identischen Abfragen sind:
Jun 30, 2016 10:59:38 AM log my-project.logging.ITVLogger
INFO: CODE00012 - Query on spreadsheet started for ID 123456
PROFILING >>> 2016-06-30T10:59:38.651+01:00 START a
10:59:38.652 [main] INFO o.a.m.d.RowPublisherDataSet -
Starting separate thread for publishing action: [email protected]
88888 NEXT >>> true <<<<
READ: 2016-06-30T10:59:39.756+01:00 >>> A_TITLE
PROFILING >>> 2016-06-30T10:59:39.756+01:00 STOP a
PROFILING >>> 2016-06-30T10:59:39.756+01:00 START b
88888 NEXT >>> false <<<<
PROFILING >>> 2016-06-30T10:59:44.735+01:00 STOP b
So ist es zu rekapitulieren dauert etwa eine Sekunde, um das Ergebnis und 4 bis 6 Sekunden für den letzten abrufen Ausführung von next()
.
Nach dem ersten '' 'next()' '' protokolliert die App '' o.a.m.d.RowPublisherDataSet - Separater Thread für die Veröffentlichung einer Aktion: org.apache.metamodel.excel.XlsxRowPublisherAction @ 3d6e18b4'''. Konnte es auf seine Beendigung warten? –
Wechseln Sie zu github.com/monitorjbl/excel-streaming-reader, lesen Sie das gesamte Dokument beim Start und halten Sie die Spalten, die ich im Speicher in einer Map benötige, damit nachfolgende Abfragen schneller sind. –