Как вы отслеживаете отношения записей в NoSQL?

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

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

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

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

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

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

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

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

  • Более того - вероятно, список клубов как свойство студента и индекс в этом поле, чтобы получить всех членов клуба

Ответ 3

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

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

Riak также имеет еще один "механизм". Он имеет 2-слойное пространство имен ключей, так называемое ведро и ключ. Итак, для примера для студентов. Если у нас есть клуб 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. Вам нужно посмотреть конкретную реализацию и проверить ее для себя.

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

удача

Ответ 4

У вас есть

"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 или документацию.

Ответ 5

Я думаю, что RavenDB предлагает хорошее решение этой проблемы с индексированием. Информация на главной странице http://ravendb.net/ объясняет концепцию достаточно хорошо, чтобы вы могли создать что-то аналогичное для вашей технологии.