Оптимизированная Массовая (Чанковая) Загрузка Объектов В IndexedDB


Я хочу добавить объекты в некоторую таблицу в IndexedDB в одной транзакции:

_that.bulkSet = function(data, key) {
    var transaction = _db.transaction([_tblName], "readwrite"),
        store = transaction.objectStore(_tblName),
        ii = 0;

    _bulkKWVals.push(data);
    _bulkKWKeys.push(key);

    if (_bulkKWVals.length == 3000) {
        insertNext();
    }

    function insertNext() {
        if (ii < _bulkKWVals.length) {
            store.add(_bulkKWVals[ii], _bulkKWKeys[ii]).onsuccess = insertNext;
            ++ii;
        } else {
            console.log(_bulkKWVals.length);
        }
    }
};

Похоже, что это работает нормально, но это не очень оптимизированный способ сделать это, особенно если количество объектов очень велико (~50.000-500.000). Как я могу его оптимизировать? В идеале я хочу добавить сначала 3000, затем удалить его из массива, а затем добавить еще 3000, а именно кусками. Есть идеи?

2 5

2 ответа:

Вставляя это количество строк последовательно, невозможно получить хорошую производительность.

Я IndexedDB dev и имею реальный опыт работы с IndexedDB в масштабе, о котором вы говорите (написание сотен тысяч строк подряд). Это не слишком красиво.

На мой взгляд, IDB не подходит для использования, когда большой объем данных должен быть записан последовательно. Если бы мне нужно было создать приложение IndexedDB, которое нуждалось бы в большом количестве данных, я бы нашел способ посевайте его медленно с течением времени.

Проблема заключается в записи, и проблема, как я вижу, заключается в том, что медленность записи в сочетании с их интенсивным характером ввода-вывода со временем ухудшается. (Читает всегда быстро в IDB, чего бы это ни стоило.)

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

Я не уверен, какую производительность вы видите, но средние цифры могут обмануть вас в зависимости от размера вашего теста. Ограничение скорости-это пропускная способность,но если вы пытаетесь вставить большие объемы данных последовательно, обратите внимание на записи с течением времени.

Я работаю над демонстрацией с несколькими сотнями тысяч строк в моем распоряжении, и у меня есть статистика. С отключенной визуализацией, запускающей pure dash на IDB, вот что я вижу сейчас в Chrome 32 на одном хранилище объектов с одним не уникальным индексом С автоматически увеличивающимся первичным ключом.

Гораздо, гораздо меньший набор данных 27k строк, я видел 60-70 записей в секунду:
* ~30 секунд: в среднем 921 запись/секунда (всегда есть большой всплеск вставок в начале), 62/секунда в момент, когда я пробовал
* ~60 секунд: среднее значение 389/сек (устойчивое снижение, начиная с перевешивает эффект начального всплеска) 71/сек в момент
* ~1: 30: 258/секунда, 67 / секунда в момент
* ~2: 00 (~1/3 сделано): 188/сек в среднем, 66 / сек в данный момент

Некоторые примеры с гораздо меньшим набором данных показывают гораздо лучшую производительность, но схожие характеристики. То же самое с гораздо большими наборами данных - эффекты сильно преувеличены, и я видел всего лишь

IndexedDB фактически предназначена для оптимизации массовых операций. Проблема в том, что спецификация и некоторые документы не рекламируют то, как это работает. Если обратить определенное внимание на детали в спецификации IndexedDB , которая определяет, как работают все мутирующие операции в IDBObjectStore (add (), put (), delete ()), вы обнаружите, что это позволяет вызывающим вызовам вызывать их синхронно и пропускать прослушивание событий успеха, кроме последнего. Опуская делать это (но все еще слушать onerror), вы получите огромный прирост производительности.

Это пример использования Dexie.js показывает возможную массовую скорость , когда он вставляет 10 000 строк за 680 МС на моем macbook pro (используя Opera / Chromium).

Выполнено по таблице.метод bulkPut () в Dexie.библиотека js:

db.objects.bulkPut(arrayOfObjects)