Как обрабатывать циклические документы в MongoDB / DynamoDB? - PullRequest
1 голос
/ 12 марта 2019

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

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

Так, например, схема ACTOR:

ACTOR1
- AGE
- BIO
- MOVIES
    - FILM1 (ties to the FILM1 document)
    - FILM2

Тогда схема MOVIE:

FILM1
- RELEASE DATE
- ACTORS
    - ACTOR1 (ties back to the ACTOR document)
    - ACTOR2

Скорость наиболееважная вещь для меня.Я могу легко добавить идентификаторы в документ ACTOR вместо полного документа MOVIE.Однако я вернулся к нескольким звонкам.Существуют ли какие-либо функции в базе данных NoSQL, такие как MongoDB или DynamoDB, которые могут решить эту проблему за один вызов?Или NoSQL просто не правильный выбор?

1 Ответ

1 голос
/ 12 марта 2019

В то время как NoSQL обычно рекомендует денормализацию моделей данных, лучше не иметь неограниченный список в одной записи базы данных. Чтобы смоделировать эти данные в DynamoDB, вы должны использовать список смежности для моделирования отношения «многие ко многим» . Я не знаю экономически эффективного способа моделирования данных, который позволил бы вам получать все нужные данные за один вызов. Однако вы сказали, что скорость важнее всего (без требования к задержке), поэтому я постараюсь дать вам представление о том, как быстро вы можете получать данные, если они хранятся в DynamoDB.

Ваши схемы станут примерно такими:

Actor {
    ActorId, <-- This is the application/database id, not the actor's actual ID
    Name,
    Age,
    Bio
}

Film {
    FilmId, <-- This is the application/database id for the film
    Title,
    Description,
    ReleaseDate
}

ActedIn {
    ActorId,
    FilmId
}

Чтобы указать, что актер сыграл роль в фильме, вам нужно выполнить только одну запись (что в моем опыте составляет последовательно однозначные миллисекунды с использованием DynamoDB), чтобы добавить элемент ActedIn в вашу таблицу.

Чтобы получить все фильмы для актера, вам нужно будет один раз запросить, чтобы получить все действующие отношения, а затем прочитать пакет, чтобы получить все фильмы. Типичные задержки для запроса (по моему опыту) составляют менее 10 мс, в зависимости от скорости сети и объема данных, передаваемых по сети. Поскольку отношение ActedIn является таким небольшим объектом, я думаю, вы могли бы ожидать в среднем 5 мс для запроса, если ваш запрос происходит от чего-то, что также выполняется в центре обработки данных AWS (EC2, Lambda и т. Д.).

Получение одного элемента будет менее 5 мс, и вы можете сделать это параллельно. Существует также API BatchGetItems, но у меня нет для вас статистики по этому вопросу.

Итак, ~ 10 мс достаточно для вас?

Если нет, вы можете использовать DAX , который добавляет уровень кэширования в DynamoDB и обещает задержку запроса <1 мс. </p>

Что такое не поддерживаемый, не рентабельный способ сделать это за один звонок?

Для каждого отношения ActedIn сохраняйте свои данные следующим образом:

ActedIn {
    ActorId,
    ActorName,
    ActorAge,
    ActorBio,
    FilmId,
    FilmTitle,
    FilmDescription,
    FilmReleaseDate
}

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

Я не уверен; похоже, что NoSQL ужасен для этого.

Вы должны помнить, что NoSQL существует во многих вариантах (NoSQL = не только SQL), и поэтому даже если одно решение NoSQL не работает для вас, вы не должны полностью исключать его. Если это абсолютно необходимо в одном вызове, вам следует рассмотреть возможность использования Graph database (это другой тип базы данных NoSQL).

...