Комментарии 26
А не рассматривали встроеный способ insert/update с использованием ContentValues?
final ContentValues values = new ContentValues(2);
values.put("id", 10);
values.put("title", "my title");
// db.update("Test", values, "id=10", null);
db.insert("Test", null, values);
0
Да. Рассматривался.
Он делает всё тоже самое что мы тут вместе с execSQL, готовит строку, подготавливает стейтмент, байндит к нему значения. В общем не быстро. Это можно посмотреть в исходниках андроида, что там внутри.
Посмотрите метод public long insertWithOnConflict из «Android SDK\sources\android-14\android\database\sqlite\SQLiteDatabase.java»
Он делает всё тоже самое что мы тут вместе с execSQL, готовит строку, подготавливает стейтмент, байндит к нему значения. В общем не быстро. Это можно посмотреть в исходниках андроида, что там внутри.
Посмотрите метод public long insertWithOnConflict из «Android SDK\sources\android-14\android\database\sqlite\SQLiteDatabase.java»
0
Я бы предложил в приложении оставить только базовые вещи, а языковые настройки вынести в отдельные apk, которые можно будет подгружать по мере необходимости. Такой вариант не рассматривался?
0
Ну. Всё приложение строится вокруг этой базы с информацией о городах, и от того, сколько в том или ином языке в базе есть названий. Т.е. как раз названия на том или ином языке — и есть базовая вещь. Всё в приложении вертится вокруг них. Рассматривался вариант качать отдельную базу для каждого языка (базу только с переводами), но это большое дублирование информации, как минимум на уровне айдишников (ведь в каждой базе будет 40 000 одних и тех же айдишников для связки полей). Хотя наверно и такой вариант подошёл бы :)
Но я выбрал тот путь что выбрал, и в итоге получился интересный исследовательский труд, да и результат тоже был достигнут. Исходная АПК не слишком велика, а языков поддерживается много.
Но я выбрал тот путь что выбрал, и в итоге получился интересный исследовательский труд, да и результат тоже был достигнут. Исходная АПК не слишком велика, а языков поддерживается много.
0
А вариант с методом ContentResolver.applyBatch и ContentProviderOperation не пробовали? Вполне прилично у меня прибавил производительности.
0
Я не очень хорошо знаком с SQLite, но, подозреваю, что она тоже поддерживает синтаксис:
Т.е. 3 запроса схлопываются в один.
update my_table
set col1 = 1, col2 = 2
where id = 3
Т.е. 3 запроса схлопываются в один.
+2
Да. Всё верно. Это поддерживается.
Просто примеры кода с 3мя запросами.
Надо упомянуть об этом в статье. Я до этого тоже не сразу додумался, хотя очевиднейшее улучшение.
Спасибо.
Просто примеры кода с 3мя запросами.
Надо упомянуть об этом в статье. Я до этого тоже не сразу додумался, хотя очевиднейшее улучшение.
Спасибо.
0
Ну тогда до кучи: обычно вставка сильно дешевле обновления.
Я бы попробовал сделать отдельную таблицу с языко-зависимыми данными (т.е. те 3 поля + язык + id в исходной таблице), а дальше — получение данных join'ами.
Ещё можно удалять данные (одной транзакцией) и вставлять заново, если схема данных приложения это позволяет.
(но это скорее идея для эксперимента)
Я бы попробовал сделать отдельную таблицу с языко-зависимыми данными (т.е. те 3 поля + язык + id в исходной таблице), а дальше — получение данных join'ами.
Ещё можно удалять данные (одной транзакцией) и вставлять заново, если схема данных приложения это позволяет.
(но это скорее идея для эксперимента)
+5
а через ATTACH DATABASE разве нельзя было решить задачу?
в смысле, подкачать дополнительную базу с переводами, соединить с основной, а при выборке данных просто JOIN-ить с таблицей из присоединённой базы.
делал подобное в базе на 8-10К записей, и производительность (чтения) была очень приемлемой для мобильного устройства. подключение же дополнительных данных вообще было мгновенным.
в смысле, подкачать дополнительную базу с переводами, соединить с основной, а при выборке данных просто JOIN-ить с таблицей из присоединённой базы.
делал подобное в базе на 8-10К записей, и производительность (чтения) была очень приемлемой для мобильного устройства. подключение же дополнительных данных вообще было мгновенным.
+1
Не туда написал ответ
0
1. вставка намного быстрее update, как уже указали. Можно в отдельную таблицу. Можно в отдельную БД и attach.
2. возможно немного быстрее будет не полное оборачивание всего обновления в одну транзакцию, а commit каждые 1000-5000 операций
3. если данные сжаты gzip, то проще всего вообще скачивать SQL в виде одной большой строки: BEGIN; INSERT; INSERT;… COMMIT; BEGIN;… COMMIT и передать его весь сразу на выполнение. Отпадает нужда в переходе на C++, так как выполнение одного большого скрипта и там, и там будет примерно одинаково. И парсить ничего не нужно.
4. можно попробовать подшаманить SQLite, отключив журнал на время обновления, например. Есть риск потерять БД, если приложение будет «убито» во время обновления, но пользователь ведь может тупо переставить приложение, верно?
5. можно исполнить скачанный SQL на базе в памяти и приаттачить ее к БД на диске. приложение сразу начнет работать, а фоновым процессом будет перекачивать базу из памяти на диск.
2. возможно немного быстрее будет не полное оборачивание всего обновления в одну транзакцию, а commit каждые 1000-5000 операций
3. если данные сжаты gzip, то проще всего вообще скачивать SQL в виде одной большой строки: BEGIN; INSERT; INSERT;… COMMIT; BEGIN;… COMMIT и передать его весь сразу на выполнение. Отпадает нужда в переходе на C++, так как выполнение одного большого скрипта и там, и там будет примерно одинаково. И парсить ничего не нужно.
4. можно попробовать подшаманить SQLite, отключив журнал на время обновления, например. Есть риск потерять БД, если приложение будет «убито» во время обновления, но пользователь ведь может тупо переставить приложение, верно?
5. можно исполнить скачанный SQL на базе в памяти и приаттачить ее к БД на диске. приложение сразу начнет работать, а фоновым процессом будет перекачивать базу из памяти на диск.
+5
create virtual table using module со ссылкой на CSV, а затем insert () into select from не подошёл?
Извините, я sqlite сам не пользовал, но всегда подозреваю, что хорошие базы имеют собственные методы импорта, зачастую вполне шустрые. К слову, у Interbase и MSSQL это было получше велосипедов, хотя и не интерактивно — прогрессбар рисовать не с чего было.
Извините, я sqlite сам не пользовал, но всегда подозреваю, что хорошие базы имеют собственные методы импорта, зачастую вполне шустрые. К слову, у Interbase и MSSQL это было получше велосипедов, хотя и не интерактивно — прогрессбар рисовать не с чего было.
0
НЛО прилетело и опубликовало эту надпись здесь
C PRAGMA ковырялся и в C++ варианте выставляю
PRAGMA synchronous = OFF
PRAGMA journal_mode = MEMORY
PRAGMA synchronous = OFF
PRAGMA journal_mode = MEMORY
0
НЛО прилетело и опубликовало эту надпись здесь
1 и 2 да, дали прирост процентов в 30 (всё на том же HTC Desire в варианте нс С++)
3 — нет, у меня нет форен кеёв.
4 — индексы по новым значениям строю после всех вставок, исследовали что это быстрее вот тут
Да и вообще там много интересных идей, как в самой статье, так и в ответах.
5 — с совсем выключенным журналированием тоже быстрее процентов на 15-20.
Итог, PRAGMA-ми можно добиться тоже не плохих результатов.
Спасибо.
3 — нет, у меня нет форен кеёв.
4 — индексы по новым значениям строю после всех вставок, исследовали что это быстрее вот тут
Да и вообще там много интересных идей, как в самой статье, так и в ответах.
5 — с совсем выключенным журналированием тоже быстрее процентов на 15-20.
Итог, PRAGMA-ми можно добиться тоже не плохих результатов.
Спасибо.
0
Может, моя идея покажется бредовой, но я бы попробовал распространять локализации в виде готовой базы и подключать её в контекст SQL-запроса с помощью ATTACH DATABASE. В этом случае смена языка происходила бы мгновенно (аттачим другой файл на алиас базы локализации), но все запросы с именем пришлось бы переписать на join с таблицей этой базы.
Впрочем, есть ещё вариант: данные перелить из аттача в главную базу, но организацию цикла select-update возложить на сам движок SQLite:
Впрочем, есть ещё вариант: данные перелить из аттача в главную базу, но организацию цикла select-update возложить на сам движок SQLite:
insert or replace into CITIES (ID, NAME) select ID, NAME from ATTACHED_LOCALIZE_DB.CITIES
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Оптимизируем скорость SQL вставки на Android устройствах