Я хочу, чтобы вставлять около 700 записей в базу Android для моего следующего обновления. Какой самый эффективный способ сделать это? Из разных сообщений я знаю, что если я использую операторы Insert
, я должен обернуть их в транзакцию. Там также сообщение об использовании вашей собственной базы данных, но мне нужны эти данные, чтобы перейти в стандартную базу данных Android для Android. Обратите внимание, что это будет сделано только один раз для каждого устройства.
Некоторые идеи:
Поместите кучу операторов SQL в файл, прочитайте их в строке за раз и выполните SQL.
Поместите данные в файл CSV, или JSON, или YAML, или XML, или что-то еще. Прочитайте строку за раз и сделайте db.insert()
.
Выясните, как сделать импорт и выполнить единый импорт всего файла.
Создайте базу данных sqlite, содержащую все записи, скопируйте ее на Android-устройство и каким-то образом объедините две базы данных.
[EDIT] Поместите все операторы SQL в один файл в res/values как одну большую строку. Затем прочитайте их строку за раз и выполните SQL.
Какой лучший способ? Существуют ли другие способы загрузки данных? Возможны ли 3 и 4?
Я не верю, что есть возможный способ выполнить # 3 или # 4 в вашем списке.
Из других решений вы перечислите два, у которых файл данных содержит прямой SQL, а другой - данные в формате, отличном от SQL.
Все три будут работать отлично, но последнее предложение захватить данные из форматированного файла и построения SQL файла кажется самым чистым. Если новая возможность пакетного обновления добавлена позднее, ваш файл данных по-прежнему можно использовать или, по крайней мере, легко перерабатывать в пригодную для использования форму. Кроме того, создание файла данных является более простым и менее подверженным ошибкам. Наконец, наличие "сырых" данных позволит импортировать в другие форматы хранения данных.
В любом случае вы должны (как вы упомянули) обернуть группы вставок в транзакции, чтобы избежать создания журнала транзакций каждой строки.
Обычно каждый раз, когда используется db.insert()
, SQLite создает транзакцию (и результирующий файл журнала в файловой системе), что замедляет работу.
Если вы используете db.beginTransaction()
и db.endTransaction()
, SQLite создает только один файл журнала в файловой системе, а затем фиксирует все вставки одновременно, значительно ускоряя работу.
Вот несколько псевдокодов: Пакетная вставка в базу данных SQLite на 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();
}
Если вы хотите прервать транзакцию из-за неожиданной ошибки или чего-то еще, просто db.endTransaction()
без предварительной настройки транзакции (db.setTransactionSuccessful()
).
Другим полезным методом является использование db.inTransaction()
(возвращает true
или false
), чтобы определить, находитесь ли вы в настоящий момент в середине транзакции.
Я обнаружил, что для массовых вставок класс (явно малоиспользуемый) DatabaseUtils.InsertHelper в несколько раз быстрее, чем при использовании SQLiteDatabase.insert
.
Две другие оптимизации также помогли мне в производительности моего приложения, хотя они могут быть неприемлемы во всех случаях:
bind
значения, которые пусты или null
.У меня есть сообщение в блоге с более подробной информацией.
Этот пример ниже будет отлично работать
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();
Ну, мое решение для этого это странно, но отлично работает... Я собираю большую сумму данных и вставляю их за один раз (объемная вставка?)
Я использую команду db.execSQL(Query)
, и я строю "запрос" со следующим утверждением...
INSERT INTO yourtable SELECT * FROM (
SELECT 'data1','data2'.... UNION
SELECT 'data1','data2'.... UNION
SELECT 'data1','data2'.... UNION
.
.
.
SELECT 'data1','data2'....
)
Единственная проблема - это создание запроса, который может быть беспорядочным. Я надеюсь, что это поможет