Как отобразить многоуровневый объект на indexedDB для лучшей эффективности - PullRequest
0 голосов
/ 27 мая 2018

Мой вопрос касается размещения структуры данных в indexedDB.Я начал создавать небольшую функцию веб-страницы, которая превратилась в нечто большее, чем инструмент веб-обучения, теперь более близкий к автономному прогрессивному веб-приложению.Использование localStorage хорошо сработало, но поскольку инструмент вырос, ограничение в 5 МБ может стать проблемой для некоторых пользователей;поэтому необходимо перейти на indexedDB.

Приложение предназначено только для настольных компьютеров и позволяет пользователю создавать портфель модулей и сохранять данные на жестком диске в виде строки JSON.Когда пользователь открывает (загружает) файл в приложении, строка анализируется, и весь портфель снова записывается в localStorage, но только один модуль записывается в объект времени выполнения одновременно.Нет необходимости в «подлинной» базе данных с точки зрения поиска данных по различным полям и индексации, а только в необходимости большего объема памяти, потому что это будет слишком запутанным для пользователя, если каждый модуль в портфеледолжен быть отдельным файлом.

Большая часть данных, сохраненных в localStorage, получена из трехуровневого объекта, и ключ создается на основе пути к объекту для сохранения и извлечения данных.Например, object.level_1 [key_1] .level_2 [key_2] .level_3 [key_3] .height = 10 сохраняется как localStorage.setItem ('k1.k2.k3.h', 10).

MyВопрос в том, что при переходе к indexedDB это более эффективно: один объектный магазин, очень похожий на настроенный localStorage, или отдельный объектный магазин для каждого из трех уровней портфеля?

Если можно просмотреть один объектный магазинкак аналогично таблице из двух столбцов с одной строкой (ключом и значением) для каждой отдельной точки данных, количество строк будет больше, чем сумма счетчиков строк для трех объектов ObjectStores, где каждая строка является ключом иобъект из нескольких точек данных;но чтобы обновить отдельную точку данных в одном из трех objectStores, объект базы данных необходимо записать во временный объект, обновить точку данных и затем записать обратно в objectStore.

Вопрос в том,затем, что более эффективно: поиск в одной таблице из множества строк одного уникального ключа, указывающего на одно менее сложное значение, или поиск в одной из трех таблиц с меньшим количеством строк, но с необходимостью выполнения того, что я считаю эквивалентным JSONсинтаксический анализ, обновление значения и строковое преобразование JSON для обновления одного и того же значения в базе данных?

Хотя явно не установлено никаких ограничений, ожидаемое максимальное количество объектов уровня_1 в одном портфеле составляет около 25, где каждый из них может содержатьдо 100 объектов level_2, каждый из которых в свою очередь может содержать максимум около 5 объектов level_3.Что-либо большее, чем это, скорее всего, приведет к тому, что пользователь просто создаст отдельные портфели.

Таким образом, хранилище объектов level_1 будет иметь около 25 строк, хранилище объектов level_2 - около 2500 строк, а хранилище объектов level_3 - около 12500 строк.Каждый объект level_1 имеет около 40 точек данных;каждый объект level_2 имеет около 100 точек данных;и каждый объект level_3 имеет около 20 точек данных.Итак, я думаю, что один объектный магазин будет иметь эквивалент (25) (40) + (2500) (100) + (12 500) (20) = 501 000 строк.

Я немного опытен в извлеченииданные используют SQL из очень больших баз данных, но абсолютно ничего не знают о том, как настраивается база данных для поиска данных по ключу.Если бы пришлось искать сверху вниз, проверяя каждую из 501 000 строк, пока не был найден соответствующий ключ, то один объектный магазин кажется довольно нелепым выбором для трех объектных магазинов.Но если indexedDB использует более эффективный метод, то один объектный магазин может быть более эффективным в зависимости от того, насколько эффективно обновить значение свойства в объекте одного из трех объектных магазинов.

По профессии я не программист;Итак, я прошу прощения, если некоторые из моих терминологии неточны, и я понимаю, что мой вопрос имеет довольно базовый уровень;но мне не удалось найти какую-либо информацию, касающуюся того, как «сопоставить» объект с базой данных объектов эффективным способом.

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

РЕДАКТИРОВАТЬ / ОБНОВИТЬ:

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

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

Возможно, после замечаний Джоша хорошим способом настройки хранилищ объектов является рассмотрение того, когда и какие данные записываются в браузер.хранение на экранах, из-за отсутствия лучшего срока.В моем приложении только один модуль (объект level_1 в портфеле) когда-либо загружался в объект времени выполнения.Есть один экран для данных уровня модуля.Когда этот экран закрывается, любые изменения в данных уровня модуля записываются в хранилище.

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

На экране объекта уровня_2 пользователь добавляет объекты уровня_3 к определенным элементам уровня_2, вызывая окно, котороепоявляется в верхней части экрана level_2.Когда каждое окно закрывается, выполняется аналогичная проверка, и любые изменения данных записываются в хранилище.

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

Помимо некоторого практического правила для эффективности базы данных, вероятно, наилучший подход дляМой конкретный вопрос и обстоятельство заключается в том, чтобы закодировать его в обоих направлениях, заполнить портфель большим, чем ожидалось, числом максимальных модулей, объектов level_2 и level_3 и проверить производительность записи и чтения данных в indexedDB.Первый метод хранилища одного объекта должен быть достаточно простым для кодирования, поскольку он настроен почти так же, как localStorage.Второй подход использования как минимум трех хранилищ объектов займет больше времени, но, вероятно, это будет необходимый и полезный опыт обучения для кого-то с моим ограниченным опытом в этих областях.

Если я добьюсь успеха, я поделюсьрезультаты здесь в ближайшее время.Спасибо.

РЕДАКТИРОВАТЬ:

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

Я думаю, что будет хорошо работать несколько хранилищ объектов: одно хранилище объектов, которое содержит один полный объект для каждого модуля или данные уровня_1 в портфеле, и три или четыре хранилища объектов, которые содержат подмножества данных для «активного» илитолько загруженный модуль.

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

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

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

Это должно хорошо работать для ожидаемого максимального размера любого отдельного объекта.модуль в этом приложении;но если размер модуля станет слишком большим для браузера при полной загрузке, то для заполнения экранов можно использовать хранилища подмножества объектов;и когда пользователь выходит из модуля, подмножества могут быть собраны вместе для создания полного набора данных модуля и записаны в хранилище объектов модуля, так же как и для восстановления.

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

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

1 Ответ

0 голосов
/ 27 мая 2018

Я думаю, что вы ответите на свой собственный вопрос, поэтому мой ответ здесь только для того, чтобы подтолкнуть вас.

Основное различие между nosql и традиционной базой данных sql заключается в отсутствии query-планирование .Планирование запросов - это функциональность, предоставляемая базой данных sql, где она принимает ваш запрос, анализирует его, а затем преобразует его в алгоритм, который находит совпадающие записи и возвращает их вам в наборе результатов.Планирование запросов включает в себя выбор наиболее оптимального подхода, обычно путем попытки свести к минимуму количество задействованных шагов, объем используемой памяти или количество времени, которое пройдет.С другой стороны, вы сами по себе с nosql.Вы должны стать экспертом по планированию запросов в одночасье.

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

Чтобы ускорить это, я бы применил те же традиционные знания о нормализации и денормализации,Бойс-Кодд и нормальные формы 1-5 и все такое.nosql находится на крайнем конце денормализации.«Логическая» структура предметов, которые вы храните, не имеет значения.С nosql ваша цель не в красивой традиционной и интуитивно понятной схеме.Ваша цель - эффективно выполнять операции хранения, ваши запросы.

Итак, чтобы ответить на вопрос, вам нужно начать с простого анализа ваших операций.Перечислите операции, которые выполняет ваше приложение.Каковы наиболее частые операции?Как вы думаете, что займет больше всего времени, чтобы завершить?По операциям я не говорю ни о низкоуровневых запросах, ни о схеме вашей базы данных в nosql / sql.Это слишком глубокий уровень абстракции.Думай более абстрактно.Перечислите такие вещи, как «загрузить информацию для всех людей, которые отвечают этим условиям», «удалить этих людей там».Я подобрал некоторые из упомянутых вами запросов, но не выбрал четкий список, и этот список является важным критерием для правильного ответа.

Как только вы перечислите эти операции, я думаю,Вы ближе к ответу на свой вопрос.В качестве игрушечного примера подумайте об обновлениях.Часты ли обновления?Частые обновления указывают на то, что одно хранилище объектов является плохим, потому что вам нужно загрузить массу ненужных вещей, чтобы просто изменить одно свойство объекта.Подумайте о гранулярности.Вам нужны все свойства объекта или только некоторые?Подумайте, какая операция наиболее частая?Загружается ли список объектов по некоторым критериям?Это удаление или обновление вещей?Подумайте о том, какие вещи загружаются одновременно (совместное размещение).Когда вы загружаете один экземпляр объекта уровня 2, другие экземпляры также обычно загружаются?Если нет, то зачем хранить их вместе?Отойди от своей нормализованной схемы и просто забудь об этом.Вам нужна денормализованная схема, в которой вы храните данные таким образом, чтобы оптимизировать ваши запросы.Конечный результат может быть совсем не похож на то, что вы себе представляете.

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

Редактировать: одно небольшое продолжение.Довольно противоречивая особенность баз данных и денормализации nosql заключается в том, что вы можете хранить данные несколько раз.Иногда имеет смысл хранить одни и те же данные в нескольких местах.Потому что это ускоряет запросы.И да, это создает пространство для несоответствий и нарушает правило отсутствия функциональных зависимостей в sql.Но вы можете обеспечить целостность (непротиворечивость) данных с помощью многопользовательских транзакций и некоторой осторожности.Более подробно, магазины, которые вы хотите, могут быть просто буквальными результатами запросов, которые вы планируете выполнять.Да.Создайте хранилище объектов для каждого запроса, который вы планируете выполнить.Храните данные избыточно среди всех них.Да, это звучит безумно и экстремально.И это немного преувеличено.Но этот подход является распространенным и поощряется, когда используется nosql.

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

То, что вы хотите, это хранилище объектов под названием «настройки».Каждый объект в магазине представляет объект настроек.Один объект настроек имеет такие свойства, как идентификатор настроек, имя свойства настроек, значение свойства настроек, свойство уровня 1, свойство уровня 2, свойство уровня 3.

Ваши базовые запросы на чтение могут выглядеть как SELECT * from Settings WHERE level1 = 'a' && level2 = 'b'.

Если пойти дальше, вы можете оптимизировать для определенных представлений, используя индексы.Мы могли бы создать индекс для свойства level1, индекс для свойства level2 и индекс для свойств level1 + level2 вместе взятых.

Допустим, ваша самая частая операция, которая должна быть быстрой, - это загрузкавсе настройки, относящиеся к определенной комбинации уровней 1, 2 и 3. Создайте индекс для всех 3, а затем просто выполните итерации по этому индексу.

Схема в этом примере мозгового штурма представляет собойхранилище одного объекта вместе с некоторыми индексами для ускорения определенных запросов.Учитывая, что индексы в основном являются производными хранилищами объектов, вы можете привести концептуальный аргумент, что вы практически используете несколько хранилищ, хотя на самом деле вы используете только одно.Во всяком случае, это может стать педантичным.Цель этого примера - просто продемонстрировать, что схема вашего хранилища объектов не имеет никакого отношения к тому, как вы концептуализируете иерархию портфелей и уровней.Это связано только с быстрым выполнением запросов.

...