Подтвердить что ты не робот

Как правильно хранить отношения данных с хранилищем таблиц Microsoft Azure?

Из реляционного мира вещи, очевидно, сильно отличаются от хранилища таблиц Azure. Первая важная вещь, с которой я столкнулся, заключается в том, как правильно хранить отношения "многие-ко-многим".

Например, у меня может быть система, которая отслеживает пользователей и книги, которыми они владеют. Я нашел еще одно сообщение здесь, где указано, что у пользователя есть свойство String, которое в основном хранит список идентификаторов книг, которыми владеет Пользователь. Хотя я понимаю, что иногда это общепринятый способ хранения данных, проблема в том, что Azure позволяет хранить только 64 Кбайта данных в String. Это определенно ограничивает количество книг, которые потенциально может использовать пользователь.

Другим возможным решением является дублирование данных. У меня может быть таблица, в которой хранятся все известные книги в системе. Но когда пользователь должен быть связан с книгой, я копирую данные книги в другую таблицу под названием OwnedBooks, которая по существу точно такая же, как и в таблице Book, за исключением того, что она также имеет свойство OwnedByUserID.

Существуют ли другие возможные решения?

Помимо этой проблемы, есть ли у кого-нибудь хорошие рекомендации по другим шаблонам и методам при использовании хранилища таблиц Azure?

4b9b3361

Ответ 1

Есть несколько решений для этого - все с недостатками, конечно: -)

  • Используйте таблицу сопоставления, как в RDBMS. Каждая строка будет содержать ключ книги и ключ пользователя.

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

  • Используйте таблицу сопоставления, как указано выше, но также включайте все данные Book, которые вам нужны в таблице сопоставления. Это денормализованное или дублированное решение, которое вы уже предложили в своей таблице OwnedBooks.

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

  • Храните клавиши книги, объединенные в одном свойстве пользователя. Опять же, вы уже предложили этот метод.

    На самом деле это было бы не так уж плохо, если бы не тот факт, что Azure в настоящее время не поддерживает "содержит" запросы типа, т.е. вы не можете искать в подстроке, поэтому, если вы когда-либо хотели найти из которых Пользователям принадлежит определенная Книга, это было бы невозможно. Интересно, что Google App Engine поддерживает это довольно прозрачно в своей системе хранения - и также проиндексирует список для вас. В любом случае вам все равно нужно будет также извлекать каждую книгу с помощью этого метода.

  • Используйте свойство "schemaless" хранилища таблиц Azure для хранения связанных ключей книги как отдельных свойств. Например, один пользовательский объект может выглядеть следующим образом:

    { Name: "User1", Book_4325: true, Book_5123: true }

    В то время как другой может выглядеть так:

    { Name: "User2", Book_5346: true, Book_8753: true, Book_6135: true }

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

    Очевидные недостатки этого в том, что он немного хрупкий, вам нужно возиться с ключами в именах свойств, и вы не сможете использовать стандартные методы StorageClient для этого - вам придется сворачивать свои собственные, Кроме того, Azure поддерживает только 255 свойств объекта. Все, что сказал, я думаю, что он будет масштабироваться довольно хорошо - хотя я никогда не пробовал.

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

Вам просто нужно тщательно изучить ваши Случаи использования, чтобы решить, как и когда данные будут обновляться, учитывая, что атомные транзакции выходят за пределы окна. Я почти гарантирую, что вы сможете жить так, чтобы вещи были "в конечном итоге последовательными" и просто учитывали тот факт, что ваша таблица сопоставления не всегда может быть на 100% актуальной.

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

Ответ 2

Нет. Вот хороший, всеобъемлющий белый документ (ссылка .docx) в таблице Azure, в котором содержится раздел о лучших практиках. Но вы должны использовать таблицу для нереляционных свойств или мешков ORM. Если вам нужна реляционная связь в облаке, вы должны использовать базу данных SQL Azure.

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