Inserción masiva en dispositivos Android


Quiero insertar alrededor de 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 declaraciones Insert, debería envolverlas en una transacción. También hay un post sobre el uso de su propia base de datos, pero necesito estos datos para ir 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. Poner un montón de sentencias SQL en un archivo, leerlos en una línea a la vez, y ejecutar el SQL.

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

  3. Averiguar 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] Poner todas las instrucciones SQL en un solo archivo en res / valores como una cadena grande. Luego léalos 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?

Author: Community, 2010-10-05

5 answers

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

De las otras soluciones que se enumeran dos que tienen el archivo de datos contienen SQL directo, y la otra tiene los datos en un formato no SQL.

Los tres funcionarían bien, pero la última sugerencia de agarrar los datos de un archivo formateado y construir el SQL usted mismo parece la más limpia. Si la verdadera capacidad de actualización por lotes se agrega en una fecha posterior, su archivo de datos sigue siendo utilizable, o al menos fácilmente procesable en una forma utilizable. Además, la creación del archivo de datos es más sencilla y menos propensa a errores. Finalmente, tener los datos "sin procesar" permitiría la importación a otros formatos de almacenamiento de datos.

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

 8
Author: codelark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-05 05:51:39

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

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

Aquí hay algunos pseudo código de: Inserte 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 abortar 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 actualmente está en medio de una transacción.

Documentación aquí

 97
Author: Jake Wilson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-28 03:33:03

He encontrado que para inserciones masivas, los (aparentemente poco utilizados) DatabaseUtils.La clase InsertHelper es varias veces más rápida que usar 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 bloqueo interno de la base de datos también puede ayudar rendimiento.

Tengo una entrada de blog con más detalles.

 33
Author: Dan Breslau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-16 18:18:09

Bueno, mi solución para esto es un poco raro, pero funciona bien... Compilo una gran suma de datos y los inserto de una sola vez (¿inserción masiva?)

Utilizo el comando db.execSQL(Query) y construyo la "Consulta" con la siguiente instrucción...

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

 9
Author: Andrew Prat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-07 19:08:21

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();
 9
Author: arun-r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-29 16:51:26