Семейства нереляционных хранилищ — Примеры
Пример 1 — Запрос, воссозданный поверх хранилища ключ-значение
Данные сессий живут в хранилище ключ-значение, и это верно, но каталог загрузок тоже туда положили. Функция ниже отвечает на один запрос, читая всю коллекцию, что медленнее базы данных, которую она заменила. Перепишите запрос под хранилище, способное на него ответить, и скажите, для чего хранилище ключ-значение стоит сохранить.
async function downloadsAtResolution(resolution) {
const found = [];
for (const key of await store.keys("item:*")) {
const value = JSON.parse(await store.get(key));
if (value.kind === "download" && value.detail.resolution === resolution) {
found.push(value);
}
}
return found;
}
Решение
async function downloadsAtResolution(resolution) {
return collection.find({ kind: "download", "detail.resolution": resolution });
}
Хранилище ключ-значение знает только, что ключ существует и у него есть значение, поэтому любой вопрос сверх выборки по ключу приходится строить в приложении — и здесь сканирование переизобретает, причём хуже, ровно те механизмы, которых избегали. Документное хранилище индексирует поля внутри документа и отвечает на запрос само, а хранилище ключ-значение остаётся для применений, которые действительно сводятся к одному ключу: состояние сессий, кэши и простые счётчики. Каталог в документном хранилище заодно читается целиком — так записью и пользуются. Ошибка здесь в том, что выбирают меньший интерфейс, а потом воссоздают поверх него слой запросов.
Пример 2 — Что каждой нагрузке нужно от чтения
Два счётчика переносят в хранилище, распределяющее данные по машинам. Для каждого скажите, может ли чтение вернуть отставшее на миг значение и почему, и назовите цену, которая следует из принятия хранилища со своим интерфейсом.
корзина покупок чтение не должно потерять строку, которую пользователь только что добавил
число подписчиков чтение с отставанием в пару секунд не меняет ничего заметного
Решение
корзина покупок нет -> требовать согласия до подтверждения записи
число подписчиков да -> подтверждать сразу и распространять после
цена выбора: собственный интерфейс запросов продукта живёт в коде доступа к данным
Распределение данных вынуждает выбирать между требованием согласия до подтверждения записи и немедленным подтверждением с распространением после. Честный ответ следует из того, что заметил бы пользователь, — поэтому баланс счёта и число подписчиков различаются. Меньше всего считают цену переносимости: стандартный реляционный запрос часто работает без изменений на другом реляционном продукте, а у каждого нереляционного хранилища свой интерфейс, поэтому размазанный слой доступа к данным привязывает приложение к продукту. Ограничение его небольшим слоем оставляет смену хранилища решением, а не переписыванием.