Как правильно хранить отношения данных с Microsoft Azure Table Storage? - PullRequest
24 голосов
/ 12 июля 2009

Появление в реляционном мире с хранилищем таблиц Azure явно отличается. Первое, с чем я столкнулся, это как правильно хранить отношения «многие ко многим».

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

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

Есть ли другие возможные решения?

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

Ответы [ 2 ]

16 голосов
/ 12 июля 2009

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

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

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

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

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

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

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

  4. Используйте «безсхемную» природу хранилища таблиц 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%.

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

9 голосов
/ 12 июля 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...