2011-12-06 19 views
5

Sto utilizzando l'API di Google Spreadsheet per aggiornare un foglio di calcolo con molti dati (centinaia di righe e una ventina di colonne).Qual è il modo più rapido per aggiornare un foglio di calcolo google con molti dati tramite l'API del foglio di calcolo?

Ho provato a effettuare una chiamata batch per aggiornare 2500 celle. La chiamata richiede circa 40 secondi per essere completata, con una richiesta di circa 1 MB e una risposta di ~ 2 MB.

C'è un modo per farlo funzionare più velocemente?

+0

stai utilizzando feed di celle o feed di elenchi? – Simon

+0

uso i feed delle celle – Daniel

risposta

1

Se si sta aggiornando intere linee, si può provare a lavorare con i feed basati su elenco:

http://code.google.com/intl/fr-FR/apis/spreadsheets/data/3.0/developers_guide.html#UpdatingListRows

Essa vi permetterà di aggiornare i valori (non le formule).

Se avete ancora problemi di prestazioni, si dovrebbe passare a qualcosa di simile a un server di database relazionale o datastore di Google (se si sta lavorando con il motore app Google)

+1

Grazie. Ma ho capito che non c'è modo di fare un aggiornamento in batch delle righe così significherebbe centinaia di richieste.http: //www.google.com/support/forum/p/apps-apis/thread? Tid = 5db19d43cb454e7e & hl = it L'utilizzo di un altro datastore non è un'opzione per me poiché la mia app è stata creata per manipolare i fogli di lavoro di google e non archiviare questi dati. – Daniel

11

sono stato in grado di accelerare la richiesta di lotti previsto nella API ufficiale http://code.google.com/apis/spreadsheets/data/3.0/developers_guide.html#SendingBatchRequests saltando la parte QUERY prima dell'aggiornamento. Quindi questo è ciò che hanno nell'esempio:

// Prepare the update 
    // getCellEntryMap is what makes the update fast. 
    Map cellEntries = getCellEntryMap(ssSvc, cellFeedUrl, cellAddrs); 

    CellFeed batchRequest = new CellFeed(); 
    for (CellAddress cellAddr : cellAddrs) { 
     URL entryUrl = new URL(cellFeedUrl.toString() + "/" + cellAddr.idString); 
     CellEntry batchEntry = new CellEntry(cellEntries.get(cellAddr.idString)); 
     batchEntry.changeInputValueLocal(cellAddr.idString); 
     BatchUtils.setBatchId(batchEntry, cellAddr.idString); 
     BatchUtils.setBatchOperationType(batchEntry, BatchOperationType.UPDATE); 
     batchRequest.getEntries().add(batchEntry); 
    } 
    // Submit the update 
    Link batchLink = cellFeed.getLink(Link.Rel.FEED_BATCH, Link.Type.ATOM); 
    CellFeed batchResponse = ssSvc.batch(new URL(batchLink.getHref()), batchRequest); 

e questo è ciò che ho cambiato in

CellFeed batchRequest = new CellFeed(); 
     for (CellInfo cellAddr : cellsInfo) { 
      CellEntry batchEntry = new CellEntry(cellAddr.row, cellAddr.col, cellAddr.idString); 
       batchEntry.setId(String.format("%s/%s", worksheet.getCellFeedUrl().toString(), cellAddr.idString));   
       BatchUtils.setBatchId(batchEntry, cellAddr.idString); 
       BatchUtils.setBatchOperationType(batchEntry, BatchOperationType.UPDATE); 
       batchRequest.getEntries().add(batchEntry); 



     } 

     CellFeed cellFeed = ssSvc.getFeed(worksheet.getCellFeedUrl(), CellFeed.class);  
     Link batchLink = cellFeed.getLink(Link.Rel.FEED_BATCH, Link.Type.ATOM); 

     ssSvc.setHeader("If-Match", "*"); 
     CellFeed batchResponse = ssSvc.batch(new URL(batchLink.getHref()), batchRequest); 
     ssSvc.setHeader("If-Match", null); 

Avviso, l'intestazione deve essere cambiato per farlo funzionare.

+0

Ottima risposta. Grazie. Ha lasciato cadere il tempo di inserimento a 4,5 secondi. –

+1

L'intestazione If-Match è la chiave! Grazie. –

2

Speedup: pubblicato da David Tolioupov - funziona. Alcune informazioni extra che hanno aiutato.

Esempio di come utilizzare il CellFeed, vedere CellDemo.java http://gdata-java-client.googlecode.com/svn-history/r51/trunk/java/sample/spreadsheet/cell/CellDemo.java

L'esempio ha dettagli, dettagli sufficienti che mi ha aiutato a ottimizzare il mio codice.

Come affermato da David Tolioupov, creare il CellEntry in questo modo:

CellEntry batchEntry = new CellEntry(cellAddr.row, cellAddr.col, cellAddr.idString); 
batchEntry.setId(String.format("%s/%s", cellFeedUrl.toString(), cellAddr.idString)); 

Dall'esempio:

/** 
* Returns a CellEntry with batch id and operation type that will tell the 
* server to update the specified cell with the given value. The entry is 
* fetched from the server in order to get the current edit link (for 
* optimistic concurrency). 
* 
* @param row the row number of the cell to operate on 
* @param col the column number of the cell to operate on 
* @param value the value to set in case of an update the cell to operate on 
* 
* @throws ServiceException when the request causes an error in the Google 
*   Spreadsheets service. 
* @throws IOException when an error occurs in communication with the Google 
*   Spreadsheets service. 
*/ 
private CellEntry createUpdateOperation(int row, int col, String value) 
    throws ServiceException, IOException { 
    String batchId = "R" + row + "C" + col; 
    URL entryUrl = new URL(cellFeedUrl.toString() + "/" + batchId); 
    CellEntry entry = service.getEntry(entryUrl, CellEntry.class); 
    entry.changeInputValueLocal(value); 
    BatchUtils.setBatchId(entry, batchId); 
    BatchUtils.setBatchOperationType(entry, BatchOperationType.UPDATE); 

    return entry; 
} 

Tutto ciò che serve è il cellFeedUrl, quindi creare la richiesta e inviarlo.

Problemi correlati