Извлечение родительского и дочернего элемента в одном запросе в DynamoDB

У меня есть следующие отношения один ко многим:

Account 1--* User

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

User содержит информацию на уровне пользователя, которая также может быть изменена.

Когда пользователь входит в систему, ему нужна информация как Account, так и User. (На данный момент я знаю только UserId).

В идеале я хочу разработать схему таким образом, чтобы был необходим один запрос. Однако я не могу определить, как это сделать, не дублируя Account в каждый User и, таким образом, не требуя некоторого фонового задания Lambda для распространения изменений в атрибутах Account по всем объектам User, что, к слову, похоже на большее использование ресурсов (и код для поддерживать), а не просто нормализовать данные и иметь 2 запроса при каждом входе в систему: выборка пользователя, затем выборка учетной записи (используя FK внутри объекта пользователя, который идентифицирует учетную запись).


Можно ли разработать схему, которая позволяет одному запросу извлекать как , так и, не требуя нетранзакционного фонового задания для распространения обновлений? (О транзакционных пакетных обновлениях не может быть и речи, поскольку существует ›25 пользователей.) А если нет, то является ли идея с двумя запросами лучшим/приемлемым методом?



person Lawrence Wagerfield    schedule 10.11.2020    source источник
comment
Один из подходов, который я придумал для эффективного извлечения родительского + дочернего элемента с учетом дочернего идентификатора, заключается в том, чтобы дочерний идентификатор содержал внутри себя родительский идентификатор. Затем, учитывая любой дочерний идентификатор, вы можете выполнить вызов batchGetItem, передав два PK. Хотя это по-прежнему стоит столько же, сколько 2-кратные запросы, на самом деле это так же быстро, как один запрос, учитывая, что batchGetItem будет извлекать элементы параллельно... так что вы вы ждете только самого длинного запроса... но это все еще стоит "ожидания" одного запроса, который вы делаете. Предполагается, что вы находитесь в начале проекта/можете выбрать, как генерируются идентификаторы.   -  person Lawrence Wagerfield    schedule 11.11.2020


Ответы (1)


Я сосредоточусь на одном аспекте вашего вопроса - идее с двумя запросами. Во многих случаях это действительно приемлемый метод, лучше, чем альтернативы. На самом деле во многих случаях использования NoSQL каждый видимый пользователю запрос приводит к значительно большему количеству запросов к базе данных, чем два. Фактически, часто утверждается, что именно по этой причине системы NoSQL заботятся о низких задержках хвоста (т. е. даже задержки 99-го процентиля должны быть низкими).

Вы не сказали, почему хотели избежать решения с двумя запросами. Представленная вами реализация с двумя запросами имеет два недостатка:

  1. Это более затратно: вам нужно делать два запроса вместо одного, что стоит (когда чтение короче 4 КБ) в два раза больше, чем одно чтение.
  2. Задержка удваивается, если вам нужно выполнить первый запрос, и только после этого можно выполнить второй запрос.

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

Для задержки: вы не сказали, что такое идентификатор пользователя в вашем приложении. Если это какой-то уникальный числовой идентификатор, возможно, его можно настроить так, чтобы идентификатор учетной записи можно было определить по идентификатору пользователя напрямую, без поиска в таблице (например, первые биты идентификатора пользователя — это идентификатор учетной записи). Если это так, вы можете запустить оба поиска одновременно, а не удваивать задержку. Стоимость все равно будет двойной, но не задержка.

По стоимости: если на аккаунт большое количество пользователей (вы сказали, что их больше 25 - не знаю, намного больше или нет), может быть полезно кэшировать данные аккаунта, чтобы не каждый пользовательскому поиску потребуется снова прочитать данные учетной записи - они часто могут кэшироваться. Если информация об Учетной записи редко меняется и ее согласованность не имеет большого значения (я не знаю, так ли это...), вы также можете обойтись чтением окончательной согласованности для информации об Учетной записи, что стоит половину обычного последовательное чтение.

person Nadav Har'El    schedule 10.11.2020
comment
Спасибо @Nadav, очень полезно! Что касается вы не сказали, почему вы хотели избежать решения с двумя запросами: в видеороликах re:Invent Рик Х подразумевает, что главная цель состоит в том, чтобы собрать все в один запрос и если вы нормализуйте свои данные вообще / используйте FK, вас ударят непослушной палкой. Идея составного ключа/идентификатора учетной записи в идентификаторе пользователя является аккуратной (я на самом деле опубликовал это в комментарии, так что это должен быть общий шаблон!) и это подход, который я буду использовать. Спасибо за снятие умственного запрета, который у меня был на несколько запросов! (Конечно, в каждом конкретном случае... вход в систему не будет частой операцией в этом приложении.) - person Lawrence Wagerfield; 11.11.2020