Inserción masiva en el dispositivo Android

Quiero insertar a granel unos 700 registros en la base de datos de Android en mi próxima actualización. ¿Cuál es la forma más eficiente de hacer esto? De varias publicaciones, sé que si uso las instrucciones de Insert , debería envolverlas en una transacción. También hay una publicación sobre el uso de su propia base de datos, pero necesito esta información para acceder a la base de datos estándar de Android de mi aplicación. Tenga en cuenta que esto solo se haría una vez por dispositivo.

Algunas ideas:

  1. Coloque un conjunto de instrucciones SQL en un archivo, léalas en línea a la vez y ejecute el SQL.

  2. Coloque los datos en un archivo CSV, o JSON, o YAML, o XML, o lo que sea. Lee una línea a la vez y haz db.insert() .

  3. Descubre cómo hacer una importación y hacer una sola importación de todo el archivo.

  4. Haga una base de datos sqlite que contenga todos los registros, copie eso en el dispositivo Android y de alguna manera combine las dos bases de datos.

  5. [EDITAR] Coloque todas las declaraciones SQL en un único archivo en res / values ​​como una gran cadena. Luego léelos una línea a la vez y ejecute el SQL.

¿Cuál es la mejor manera? ¿Hay otras formas de cargar datos? ¿Son 3 y 4 incluso posibles?

No creo que haya ninguna forma factible de lograr # 3 o # 4 en su lista.

De las otras soluciones, enumera dos que tienen el archivo de datos que contiene SQL directo, y el otro tiene los datos en un formato no SQL.

Los tres funcionarían bien, pero la última sugerencia de capturar los datos de un archivo formateado y crear el SQL usted mismo parece ser el más limpio. Si se agrega la capacidad de actualización por lotes real en una fecha posterior, su archivo de datos aún se puede usar, o al menos se puede procesar fácilmente en una forma utilizable. Además, la creación del archivo de datos es más directa y menos propensa a errores. Finalmente, tener los datos “en bruto” permitiría la importación a otros formatos de almacenamiento de datos.

En cualquier caso, debe (como ha mencionado) ajustar los grupos de insertos en las transacciones para evitar la creación del diario de transacciones por fila.

Normalmente, cada vez que se utiliza db.insert() , SQLite crea una transacción (y el archivo de diario resultante en el sistema de archivos), lo que ralentiza las cosas.

Si usa db.beginTransaction() y db.endTransaction() SQLite crea solo un único archivo de diario en el sistema de archivos y luego confirma todas las inserciones al mismo tiempo, acelerando drásticamente las cosas.

Aquí hay un pseudo código de: Inserción por lotes a la base de datos SQLite en Android

 try { db.beginTransaction(); for each record in the list { do_some_processing(); if (line represent a valid entry) { db.insert(SOME_TABLE, null, SOME_VALUE); } some_other_processing(); } db.setTransactionSuccessful(); } catch (SQLException e) {} finally { db.endTransaction(); } 

Si desea cancelar una transacción debido a un error inesperado o algo así, simplemente db.endTransaction() sin establecer primero la transacción como exitosa ( db.setTransactionSuccessful() ).

Otro método útil es usar db.inTransaction() (devuelve true o false ) para determinar si se encuentra actualmente en el medio de una transacción.

Documentación aquí

Descubrí que para las inserciones masivas, la clase DatabaseUtils.InsertHelper (aparentemente poco utilizada) es varias veces más rápida que con SQLiteDatabase.insert .

Otras dos optimizaciones también ayudaron con el rendimiento de mi aplicación, aunque pueden no ser apropiadas en todos los casos:

  • No bind valores que estén vacíos o null .
  • Si puede estar seguro de que es seguro hacerlo, desactivar temporalmente el locking interno de la base de datos también puede ayudar al rendimiento.

Tengo una publicación en el blog con más detalles.

Bueno, mi solución para esto es un poco rara pero funciona bien … Recopilo una gran cantidad de datos y los inserto de una vez (¿insertar a granel?)

Uso el db.execSQL(Query) y construyo la “Consulta” con la siguiente statement …

 INSERT INTO yourtable SELECT * FROM ( SELECT 'data1','data2'.... UNION SELECT 'data1','data2'.... UNION SELECT 'data1','data2'.... UNION . . . SELECT 'data1','data2'.... ) 

El único problema es la construcción de la consulta que puede ser un poco desordenada. Espero que ayude

Este ejemplo a continuación funcionará perfectamente

  String sql = "INSERT INTO " + DatabaseHelper.TABLE_PRODUCT_LIST + " VALUES (?,?,?,?,?,?,?,?,?);"; SQLiteDatabase db = this.getWritableDatabase(); SQLiteStatement statement = db.compileStatement(sql); db.beginTransaction(); for(int idx=0; idx < Produc_List.size(); idx++) { statement.clearBindings(); statement.bindLong(1, Produc_List.get(idx).getProduct_id()); statement.bindLong(2, Produc_List.get(idx).getCategory_id()); statement.bindString(3, Produc_List.get(idx).getName()); // statement.bindString(4, Produc_List.get(idx).getBrand()); statement.bindString(5, Produc_List.get(idx).getPrice()); //statement.bindString(6, Produc_List.get(idx).getDiscPrice()); statement.bindString(7, Produc_List.get(idx).getImage()); statement.bindLong(8, Produc_List.get(idx).getLanguage_id()); statement.bindLong(9, Produc_List.get(idx).getPl_rank()); statement.execute(); } db.setTransactionSuccessful(); db.endTransaction();