2010-11-08 3 views
84

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

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

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

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

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

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

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

+0

Нет никакого способа сделать это в базах данных NoSQL, этот вопрос - это скорее вопрос, как бы отслеживать отношения в программах на C. – stonemetal

+3

Ничего себе, тогда я думаю, что шумиха о NoSQL, заменяющем СУБД, невозможна. – Xeoncross

+10

Да, NoSQL определенно превышен. Я не говорю, что новые технологии не пригодились при правильных обстоятельствах, но смешно думать, что они заменят РСУБД. См. Http://en.wikipedia.org/wiki/Hype_cycle –

ответ

124

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

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

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

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

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

+11

«вам не следует использовать решение NoSQL, если вам нужно использовать данные реляционным способом». Так как другие, работающие с NoSQL, уходят с ним? Как вы можете знать все способы запроса данных при первом создании приложения? Пример Fox, мне бы хотелось, чтобы последние комментарии, комментарии пользователя, комментарии по тегу, комментарии для данного сообщения, комментарии помечены как спам, активные комментарии, наивысшие оценки и т. Д. – Xeoncross

+7

Точно - нет такой вещи, как " он просто работает », как утверждают сторонники NoSQL. Либо вы делаете кучу анализа перед вашим реляционным моделированием данных, либо выполняете кучу анализа перед вашими приоритетными запросами, либо выполняете кучу дорогостоящего рефакторинга по всему проекту, когда вы обнаруживаете, какие части вашего дизайна не получил достаточно анализа вперед. –

+0

@Xeoncross Я также понимаю эту проблему. Посмотрите на вторичные индексы. Как правило, NoSQL создает вторичные индексы для соответствия различным случаям использования бизнеса. Хотя предпочтительнее меньшее количество вторичных индексов. –

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

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

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

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

+0

Итак, в основном все, что нужно спискам? Похоже, что должен быть более сложный подход, чем просто отслеживание строк идентификаторов вручную. Во-первых, вы можете только зайти так далеко, прежде чем они станут полезными. Опять же, основные проекты плаката-ребенка в технологии NoSQL (MongoDB, CouchDB, Membase и т. Д.) - это все новые проекты, поэтому, возможно, мне просто нужно дать им больше времени, чтобы придумать лучший способ отслеживания отношений. – Xeoncross

+0

Если вы используете NoSQL (не реляционные хранилища данных AKA), вам нужно перестать думать в реляционных терминах. Используемый подход будет отличаться между платформами, но основная идея, что вам нужно управлять индексами, является достаточно универсальной. Примеры отношений, которые вы указали, моделируются двумя способами в NoSQL: 1) Storage - в отличие от SQL, столбцы могут иметь несколько/сложных значений, поэтому дочерний объект является только частью родительского объекта. 2) Поиск. Ваши длинные списки на самом деле являются требованием для поиска, что означает индексирование - вы можете использовать простой пользовательский список или более полную поисковую систему. –

3

CouchDB подход предлагает испускает соответствующие классы материала в фазе карты и обобщать ее в уменьшить .. Так что вы можете отобразить все комментарии и испускаете 1 для данного пользователя, а затем распечатать только те.Однако для хранения постоянных представлений всех отслеживаемых данных в couchDB потребуется много дискового хранилища. Кстати, у них есть и эта страница вики об отношениях: 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. Вам нужно посмотреть конкретную реализацию и проверить ее для себя.

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

удачи

+1

Riak недавно выпустил v1.0, который добавляет поддержку вторичных индексов при использовании бэкэнда LevelDB. Очень ценная особенность. –

0

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

1

Вы

"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 (A .NET based NoSQL Database with SQL support) Ваши запросы будут как

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

Смежные вопросы