Как вы отслеживаете рекордные отношения в NoSQL?


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

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

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

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

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

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

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

4 94

4 ответа:

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

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

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

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

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

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

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

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

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

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

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

У РИАК есть еще один "механизм". Он имеет 2-слойное пространство имен ключей, так называемое ведро и ключ. Так, например, если у нас есть клуб A, B и C и студент StudentX, Студенты вы могли бы поддерживать следующее соглашение:

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

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

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

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

удачи

у вас есть

"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. Просто индексируйте поля, с которыми вы будете получать информацию.

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

  • комментарий.Имя пользователя
  • комментарий.PageID
  • комментарий.PostTime
  • страница.Тег[]

Если вы используете 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 шпаргалка или документации.