IndexedDB и большое количество вставок в приложении Angular

Я борюсь с количеством 20-50k ответов объекта JSON с сервера, которые я должен вставить в наше хранилище данных indexeddb.

Ответ повторяется с foreach, и каждая отдельная строка добавляется с каждым. Вызовы с ответом менее 10 тыс. строк работают нормально и вставляются в течение минуты или около того. Но когда суммы становятся больше, база данных через некоторое время перестает отвечать на запросы и возвращает это сообщение об ошибке.

"db Error err=транзакция прервана по неизвестной причине"

Я использую оболочку Dexie для базы данных и угловую оболочку для dexie, которая называется ngDexie.

var deferred = $q.defer();
var progress = 0;
 // make the call
 $http({
       method: 'GET',
       headers: headers,
       url: '/Program.API/api/items/getitems/' + user
            }).success(function (response) {

        // parse response
        var items = angular.fromJson(response);
        // loop each item
        angular.forEach(items, function (item) {    
                    // insert into db
                    ngDexie.put('stuff', item).then(function () {
                        progress++;
                        $ionicLoading.show({
                            content: 'Loading',
                            animation: 'fade-in',
                            template: 'Inserting items to db: ' + progress
                                       + '/' + items.length,
                            showBackdrop: true,
                            maxWidth: 200,
                            showDelay: 0

                        });

                        if (progress == items.length) {
                            setTimeout(function () {
                                $ionicLoading.hide();
                            }, 500);
                            deferred.resolve(items);

                        }      
                    });
                });
            }).error(function (error) {
                $log('something went wrong');
                $ionicLoading.hide();
            });
            return deferred.promise;

У меня неправильный подход к работе со всеми данными в одном фрагменте? Может есть лучшие альтернативы? Вся эта процедура выполняется только один раз, когда пользователь открывает сайт. Вся помощь приветствуется. Целевое устройство — планшеты под управлением Android с Chrome.


person poptard    schedule 08.11.2015    source источник


Ответы (3)


Поскольку вы получаете неизвестную ошибку, что-то не так с вводом-выводом. Я предполагаю, что у базы данных внизу есть проблемы с обработкой данных. Можно попробовать разделить на партии максимум по 10к каждая.

Транзакция может завершиться неудачей по причинам, не связанным с конкретным IDBRequest. Например, из-за ошибок ввода-вывода при фиксации транзакции или из-за ограничения квоты, когда реализация не может связать превышение квоты с конкретным запросом. В этом случае реализация ДОЛЖНА выполнить шаги для прерывания транзакции, используя транзакцию как транзакцию и соответствующий тип ошибки как ошибку. Например, если квота была превышена, то в качестве ошибки следует использовать QuotaExceededError, а если произошла ошибка ввода-вывода, в качестве ошибки следует использовать UnknownError.

вы можете найти это в спецификациях

Другая возможность: есть ли у вас какие-либо индексы, определенные в хранилище объектов? Потому что для каждого имеющегося у вас индекса этот индекс необходимо поддерживать при каждой вставке.

person Kristof Degrave    schedule 08.11.2015
comment
Спасибо, что уделили мне время, чтобы ответить, я должен провести больше исследований по этому вопросу, но у нас есть нетерпеливый клиент, желающий начать работу завтра. Теперь я попытаюсь сделать куски по 5k каждый и молиться, чтобы это сработало. И да, у нас есть определенные индексы. Я не опытный пользователь IndexedDB, так как это быстрый проект, так что вы подразумеваете под их поддержкой? - person poptard; 08.11.2015
comment
В indexeddb индексы фактически также являются хранилищами объектов, единственная разница в том, что ключ этого хранилища объектов является значением пути ключа, определенного в индексе, а значения представляют собой набор объектов, которые соответствуют ключу. - person Kristof Degrave; 08.11.2015

Если вы вставляете много новых записей, я бы предложил использовать add. Это было добавлено из соображений производительности. Смотрите документацию здесь:

https://github.com/FlussoBV/NgDexie/wiki/ngDexie.add

person Martin Diphoorn    schedule 14.09.2016

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

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

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

BulkPut() -> http://dexie.org/docs/Table/Table.bulkPut()

person Francesco    schedule 16.06.2017