Повышение производительности при массивной вставке IndexedDB

Мы пытаемся предварительно кэшировать большую сумму данных при загрузке нашего веб-приложения в индексированную базу данных. Из моего тестирования производительности скорость приличная в настольном браузере (например, Internet Explorer), где я могу вставить 10 000 записей примерно за 2 секунды. Но по сравнению с точно такой же функциональностью на iPad оно падает до 30 секунд. Это сравнение просто поразило меня.

Кто-нибудь знает какие-либо подсказки или приемы для вставки больших наборов данных в indexedDB. Я не знаю, возможно ли это вообще, но если бы мы могли создать копию серверной части indexedDB со всеми предварительно заполненными данными, а затем просто передать их клиенту, и он просто сохранит их в браузере. Что-нибудь в этом направлении выполнимо?

Спасибо


person Matt    schedule 25.03.2015    source источник
comment
взгляните на этот вопрос 25914265/   -  person Deni Spasovski    schedule 30.03.2015
comment
Я не уверен, что это что-то меняет, но если вы тестировали Chrome на настольном компьютере, то разница может быть в значительной степени связана с различиями между Chrome и Safari, а не только с настольным компьютером и мобильным устройством. См. stackoverflow.com/questions /41824512/   -  person nbrustein    schedule 05.03.2017


Ответы (3)


У меня были проблемы с массовой вставкой (100 000 - 200 000 записей). Я решил все свои проблемы с производительностью IndexedDB, используя библиотеку Dexie. У него есть важная особенность:

У Декси потрясающая игра. Массовые методы используют малоизвестную функцию indexedDB, которая позволяет хранить данные без прослушивания каждого события onsuccess. Это ускоряет работу до максимума.

Декси: https://github.com/dfahlander/Dexie.js

person Francesco    schedule 16.06.2017
comment
Я прочитал (чрезвычайно разрозненный и большой) код Dexie и обнаружил (см. dbcore-indexeddb.ts), что магический соус заключается в том, что он захватывает последнюю выполненную операцию и устанавливает для нее обратные вызовы и предполагает, что все предыдущие операции были завершены к тому времени, когда эти поражены. Таким образом, при успешном выполнении последнего запроса массовой операции данные собираются и выполняется обещание. Ни один из остальных запросов не имеет обработчиков onsuccess, как указано. - person Yet Another User; 20.07.2021

Как ваши данные хранятся в indexeddb? Все ли в одном хранилище объектов или вы используете несколько хранилищ объектов. Вам нужны все кешированные данные немедленно?

Если у вас есть только одно хранилище объектов, вы можете начать с хранения всех данных, которые вам изначально нужны, зафиксировать эту транзакцию и начать новую для всех остальных. Таким образом, вы можете начать извлекать исходные данные, вставляя остальные. IndexedDB является асинхронным, поэтому он должен вас заблокировать.

Если у вас есть несколько хранилищ объектов, вы можете использовать одну и ту же стратегию. Сначала заполните хранилище объектов, которое вам нужно немедленно, и отложите остальные.

Или, возможно, рассмотрите возможность использования AppCache API вместо API-интерфейс indexeddb. Используя это, вы можете просто кэшировать файл javascript, содержащий все объекты json, которые вы хотите кэшировать. Это скорее тот случай, когда вам не нужно много запрашивать данные.

person Kristof Degrave    schedule 25.03.2015

Некоторые довольно серьезные проблемы с производительностью IndexedDB могут быть вызваны длительным периодом, когда браузер просто вызывает обратные вызовы при успехе и сталкивается с накладными расходами цикла обработки событий после фактического выполнения работы. Модель производительности, которую наблюдало мое приложение, которое делало это, заключалась в том, что оно выполняло кучу работы, а затем просто очень неэффективно отвечало на тысячи обратных вызовов:

скриншот Chrome Profiler, показывающий кучу вещей с читаемыми именами функций со сплошной заливкой, затем кучу более светлых областей, почти выделенных серым цветом

Правая часть этого изображения — это обратные вызовы для каждого запроса. Решение для этого, конечно, состоит в том, чтобы не ставить обратный вызов на каждый запрос, но раньше мне было непонятно, как это сделать.

Способ, которым Dexie.js выполняет это (подробнее см. src/dbcore/dbcore-indexeddb.ts), заключается в том, что он сохраняет последний запрос (например, IDBObjectStore.put и т. д.), и устанавливает обратный вызов onsuccess для этого, который затем собирает результаты остальных запросов. Таким образом, он избегает ада обратных вызовов.

Другой подход заключается в использовании события IDBTransaction.oncomplete. , и вообще не беспокойтесь о обратных вызовах для отдельных запросов.

(примечание: да, я знаю, сколько лет этому вопросу, сегодня у меня была эта проблема, и я хотел поставить что-то более полезное для этого вопроса, который высоко в результатах Google)

person Yet Another User    schedule 20.07.2021