2012-08-01 6 views
8

La chiamata del metodo createOrUpdate(...) di ORMLite createOrUpdate(...) nella mia app è molto lenta.La creazioneOrUpdate di ORMLite sembra lenta: qual è la velocità normale?

Ho un oggetto molto semplice (Item) con un 2 int (una è la generatedId), un String e double. Esamino il tempo necessario (approssimativamente) per aggiornare l'oggetto nel database (100 volte) con il codice seguente. I registri dichiarazione di registro:

tempo di aggiornare 1 fila 100 volte: 3069

Perché ci vuole 3 secondi per aggiornare un oggetto 100 volte, in una tabella con solo 1 fila. È questa la normale velocità ORMLite? In caso contrario, quale potrebbe essere il problema?

RuntimeExceptionDao<Item, Integer> dao = 
    DatabaseManager.getInstance().getHelper().getReadingStateDao(); 
Item item = new Item(); 
long start = System.currentTimeMillis(); 
for (int i = 0; i < 100; i++) { 
    item.setViewMode(i); 
    dao.createOrUpdate(item); 
} 
long update = System.currentTimeMillis(); 
Log.v(TAG, "time to update 1 row 100 times: " + (update - start)); 

Se creo 100 nuove righe, la velocità è ancora più lenta.

Nota: sto già utilizzando ormlite_config.txt. Registra "Loaded configuration for class ...Item" quindi questo non è il problema.

Grazie.

risposta

23

Questa potrebbe essere la velocità "attesa", sfortunatamente. Assicurati di utilizzare ORMLite versione 4.39 o successiva. createOrUpdate(...) utilizzava un metodo più costoso per verificare preventivamente l'esistenza dell'oggetto nel database. Ma sospetto che questo sarà un miglioramento minimo della velocità.

Se creo 100 nuove righe, la velocità è ancora più lenta.

Per impostazione predefinita, Sqlite è in modalità di commit automatico. Una cosa da provare è avvolgere i tuoi inserti (o i tuoi createOrUpdate s) usando il metodo ORMLite .

Nel BulkInsertsTest android unit test, il seguente metodo doInserts(...) inserisce 1000 articoli. Quando lo chiamo:

doInserts(dao); 

Ci vogliono 7,3 secondi nel mio emulatore. Se chiamo con il metodo callBatchTasks(...) che avvolge una transazione intorno alla chiamata in Android Sqlite:

dao.callBatchTasks(new Callable<Void>() { 
    public Void call() throws Exception { 
     doInserts(dao); 
     return null; 
    } 
}); 

Ci vogliono 1,6 secondi. È possibile ottenere le stesse prestazioni utilizzando il metodo dao.setSavePoint(...). Questo avvia una transazione, ma non è buono come il metodo callBachTasks(...) perché è necessario assicurarsi che si chiude la propria transazione:

DatabaseConnection conn = dao.startThreadConnection(); 
Savepoint savePoint = null; 
try { 
    savePoint = conn.setSavePoint(null); 
    doInserts(dao); 
} finally { 
    // commit at the end 
    conn.commit(savePoint); 
    dao.endThreadConnection(conn); 
} 

Questo richiede anche ~ 1,7 secondi.

+0

Grazie! Il metodo callBatchTasks lo rende molto più veloce, rende la velocità accettabile, se non perfetta. 300 ms risulteranno in un piccolo hickup quando l'utente sta scorrendo (immagino). L'unica soluzione è spostarlo in un thread separato? – Frank

+0

Passare a un thread separato, se si può effettivamente farlo in background, non bloccherà sicuramente l'interfaccia utente. Potresti provarlo @ Frank. – Gray

+1

Su un sidenote a questo, la [documentazione] (http://ormlite.com/javadoc/ormlite-core/doc-files/ormlite_5.html#index-callTask) mostra una sintassi non valida (vecchia?) Nell'esempio per 'callBatchTasks' (il primo parametro è ConnectionSource). – Czechnology