Агрегаты полезны тем, что они объединяют в одно целое данные, доступ к которым осуществляется одновременно. Однако существует много ситуаций, в которых доступ к связанным данным осуществляется по-другому. Рассмотрим связь между клиентом и всеми его заказами. Некоторые приложения требуют доступ к истории заказов каждый раз, когда они обращаются к данным о клиенте. В этом случае данные о клиенте и его истории заказов целесообразно объединить в один агрегат. Однако другие приложения желают обрабатывать заказы по отдельности и моделируют их как независимые агрегаты.
В этом случае агрегаты заказов и клиента целесообразно разъединить, сохранив между ними определенную связь, чтобы любая операция над заказом могла использовать данные о клиенте. Проще всего установить такую связь, включив идентификатор клиента в данные агрегата заказа. В этом случае, если вам потребуются данные из записи о клиенте, вы прочитаете заказ, узнаете идентификатор клиента и пошлете базе данных другой вызов, чтобы прочитать данные о клиенте. Это вполне работоспособное решение, которое прекрасно подходит для многих сценариев, но база данных не будет знать о связи между данными. Это может оказаться важным, поскольку иногда полезно, чтобы база данных знала о связях между данными.
В результате многие разработчики баз данных, даже хранилищ типа “ключ-значение”, предпринимают усилия, чтобы сделать такие отношения видимыми. Документные хранилища открывают содержимое агрегатов для баз данных, чтобы те формировали индексы и запросы. Например, Riak, хранилище типа “ключ-значение”, позволяет размещать информацию о связи в метаданных, поддерживая частичное извлечение и прослеживание связей.
Важным аспектом связей между агрегатами является их обработка модификаций. Агрегатно-ориентированные базы данных интерпретируют агрегат как единое целое при извлечении данных. Следовательно, атомарность поддерживается только в содержимом отдельного агрегата. Если вы обновляете несколько агрегатов одновременно, то должны самостоятельно реагировать на сбой при обращении к ним. Реляционные базы данных помогают пользователям тем, что позволяют модифицировать несколько записей одновременно в рамках одной транзакции, обеспечивая гарантии безопасности выполнения операций ACID при изменении нескольких строк.
Все это означает, что при обращении к нескольким агрегатам одновременно агрегатно-ориентированные базы данных становятся неудобными. Существует несколько способов смягчения этой проблемы, которые мы исследуем в следующих разделах, но фундаментальное неудобство устранить невозможно.
Следовательно, при работе с данными, между которыми установлено много связей, следует предпочесть реляционные базы данных, а не хранилище NoSQL. Несмотря на этот недостаток агрегатно-ориентированных баз данных, следует помнить, что не все реляционные базы данных великолепно справляются со сложными связями. И хотя в языке SQL вы можете формировать запросы, содержащие операции соединения, с ростом количества соединений ситуация быстро становится запутанной — как с точки зрения языка SQL, так и с точки зрения итоговой производительности.
А сейчас настал удобный момент представить вам другую категорию баз данных, которые часто относят к технологии NoSQL, это Графовые базы данных.