Как вы отслеживаете записи отношений в NoSQL? - PullRequest
109 голосов
/ 08 ноября 2010

Я пытаюсь выяснить эквивалент внешних ключей и индексов в базах данных NoSQL KVP или Document.Поскольку нет основных таблиц (для добавления ключей, обозначающих отношения между двумя объектами), я действительно озадачен тем, как вы сможете получать данные способом, который был бы полезен для обычных веб-страниц.

СкажитеУ меня есть пользователь, и этот пользователь оставляет много комментариев по всему сайту.Единственный способ отслеживать комментарии пользователей - это

  1. Встраивать их в объект пользователя (который кажется совершенно бесполезным)
  2. Создать и поддерживать user_id:commentsзначение, которое содержит список ключей каждого комментария [комментарий: 34, комментарий: 197 и т. д.], чтобы я мог получить их по мере необходимости.

Однако, взяв второй пример, вы получитескоро ударится о кирпичную стену, когда вы будете использовать ее для отслеживания других вещей, таких как ключ с именем "active_comments", который может содержать 30 миллионов идентификаторов, что делает ТРОНУ для запроса каждой страницы, чтобы узнать некоторые недавние активные комментарии,Он также будет очень склонен к условиям гонки , так как многие страницы могут попытаться обновить его одновременно.

Как я могу отслеживать отношения, подобные приведенным ниже, в базе данных NoSQL?

  • Все комментарии пользователя
  • Все активные комментарии
  • Все сообщения с тегом [ключевое слово]
  • Все студенты вклуб - или все клубы, в которых учится студент

Или я неправильно думаю об этом?

Ответы [ 4 ]

160 голосов
/ 18 ноября 2010

Все ответы о том, как хранить связи «многие ко многим» в «пути NoSQL» сводятся к одному и тому же: избыточное хранение данных.

В NoSQL вы не• Разработать вашу базу данных на основе отношений между объектами данных.Вы создаете свою базу данных на основе запросов, которые вы будете выполнять против нее.Используйте те же критерии, которые вы использовали бы для денормализации реляционной базы данных: если для данных важнее иметь сплоченность (подумайте о значениях в списке через запятую, а не в нормализованной таблице), сделайте это таким образом.

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

Существует риск денормализации и избыточности, что избыточные наборы данных будут синхронизированы друг с другом.Это называется аномалия .Когда вы используете нормализованную реляционную базу данных, СУБД может предотвращать аномалии.В денормализованной базе данных или в NoSQL вы обязаны писать код приложения для предотвращения аномалий.

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

4 голосов
/ 16 ноября 2010

Подход couchDB предлагает выдавать надлежащие классы материала на этапе отображения и суммировать его в сокращении. Таким образом, вы можете отобразить все комментарии и выдать 1 для данного пользователя, а затем распечатать только те.Однако для создания постоянных представлений всех отслеживаемых данных в couchDB потребуется много дискового пространства.Кстати, у них также есть эта вики-страница об отношениях: http://wiki.apache.org/couchdb/EntityRelationship.

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

У Риака есть еще один «механизм».Он имеет двухслойное пространство имен ключей, так называемое ведро и ключ.Так, для примера студента, если у нас есть клубы A, B и C и студент StudentX, StudentY, вы можете придерживаться следующего соглашения:

{ Key = {ClubA, StudentX}, Value = true }, 
{ Key = {ClubB, StudentX}, Value = true }, 
{ Key = {ClubA, StudentY}, Value = true }

и читать отношения просто списком ключей в данных сегментах.Что в этом плохого?Это чертовски медленно.Перечисление ведер никогда не было приоритетом для riak.Все лучше и лучше.Кстати.вы не тратите память, потому что этот пример {true} может быть связан с одним полным профилем StudentX или Y (здесь конфликты невозможны).

Как вы видите, NoSQL! = NoSQL.Вам нужно взглянуть на конкретную реализацию и протестировать ее для себя.

Упоминается до того, как хранилища столбцов выглядят хорошо подходящими для отношений ... но все зависит от ваших потребностей A и C и P;) Если вам это не нужноА и у вас меньше байтов Peta, просто оставьте его, продолжайте с MySql или Postgres.

удачи

4 голосов
/ 09 ноября 2010
  1. user: userid: comments является разумным подходом - его следует рассматривать как эквивалент индекса столбца в SQL с дополнительным требованием, чтобы вы не могли запрашивать неиндексированные столбцы.

  2. Здесь вы должны подумать о своих требованиях. Список с 30 миллионами предметов не является необоснованным, потому что он медленный, а потому, что с ним что-либо делать практически невозможно. Если ваше реальное требование состоит в том, чтобы отображать некоторые недавние комментарии, лучше хранить очень короткий список, который обновляется при добавлении комментария - помните, что NoSQL не требует нормализации. Условия гонки - это проблема со списками в базовом хранилище значений ключей, но обычно либо ваша платформа поддерживает списки должным образом, вы можете что-то делать с блокировками, либо вы фактически не заботитесь о неудачных обновлениях.

  3. То же, что и для комментариев пользователей - создайте ключевое слово индекса: posts

  4. Больше того же самого - вероятно, список клубов как собственность студента и указатель на это поле, чтобы собрать всех членов клуба

1 голос
/ 14 июля 2016

У вас есть

"user": {
    "userid": "unique value",
    "category": "student",
    "metainfo": "yada yada yada",
    "clubs": ["archery", "kendo"]
}

"comments": {
    "commentid": "unique value",
    "pageid": "unique value",
    "post-time": "ISO Date",
    "userid": "OP id -> THIS IS IMPORTANT"
}

"page": {
    "pageid": "unique value",
    "post-time": "ISO Date",
    "op-id": "user id",
    "tag": ["abc", "zxcv", "qwer"]
}

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

Например, для вас важными индексами являются

  • Comment.UserID
  • Comment.PageID
  • Comment.PostTime
  • Page.Tag []

Если вы используете NosDB (база данных NoSQL на основе .NET с поддержкой SQL) Ваши запросы будут выглядеть так:

 SELECT * FROM Comments WHERE userid = ‘That user’;

 SELECT * FROM Comments WHERE pageid = ‘That user’;

 SELECT * FROM Comments WHERE post-time > DateTime('2016, 1, 1');

 SELECT * FROM Page WHERE tag = 'kendo'

Проверьте все поддерживаемые типы запросов из их таблицы SQL или документации.

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