2016-01-25 2 views
4

В моем приложении у меня есть «статьи» (похожие на сообщения/твиты/статьи), которые помечены дескриптивными предопределенными тегами: т.е. «трудный», «простой», «красный», «синий», «бизнес» и т. Д.Всегда ли полезно хранить массив в качестве значения поля или хранить значения массива в виде записей?

Эти доступные теги хранятся в таблице, называются «тегами», которые содержат все доступные теги.

В каждую статью можно пометить несколько тегов, которые можно редактировать с помощью специального интерфейса администратора.

Это может быть заманчиво просто связать тег для каждого объекта в строковой массив идентификаторов каждого тега и хранить его вместе с записью статьи в моем «статьях» стол:

id | title | author | tags 
---+-------+--------+------------- 
1 | title | TG  | "[1,4,7,12]" 

хотя я Конечно, это плохая идея по ряду причин, есть ли разумная причина сделать это?

+0

Я не знаю PostgreSQL, но, как представляется, поддержка XML, сохранение списка тэгов в виде строки XML может принести существенные преимущества в простой список с разделителями. –

ответ

6

Думаю, вы должны прочитать о Database normalization и решить сами. Короче говоря, есть ряд проблем с вашим предложением, но вы можете решить, можете ли вы с ними жить.

Наиболее очевидные из них:

  1. Что делать, если дополнительный тег добавляется к строке (1)? Вы должны сначала разобрать, проверить, если он уже присутствует, а затем обновить строку, которая должна быть tags.append(newTag).
  2. Хуже того, удаляя тег? Поисковые теги, есть, воссоздают теги.
  3. Что делать, если тег должен изменить имя - возможно, какой-то процесс модерации?
  4. Хуже того, как насчет dfferent людей, определяющих имя тега по-другому - было бы трудно рационализировать.
  5. Что делать, если вы хотите запросить данные на основе тегов? Ваш запрос становится намного сложнее, чем нужно.
  6. Презентация: Клиент должен проанализировать тег, чтобы использовать его. Как насчет поля разделителя? Измените это, и все клиенты должны измениться.

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

2

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

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

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

0

Я полностью согласен с тем, что это CAN - хорошая идея.Я являюсь сильным сторонником хранения тегов в базе данных в виде отдельного списка строк.

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

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

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

Я предлагаю вам хранить данные в виде строки с разделителями и использовать внешнюю службу индексирования для обеспечения поиска и анализа ваших данных. Это хороший компромисс между попытками доступа к данным CRUD для управления данными и индексами для оптимизации поиска. Конечно, вы можете оптимизировать БД и поисковые запросы, чтобы заставить его работать в SQL, но это может приложить все усилия, чтобы исправить это.

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

+1

. Разделяемая запятая строка, конечно, НЕ является тем, как идти сюда. В PostgreSQL имеется ряд индексов на основе GIST/GIN, которые будут выполнять поиск в массиве целых чисел или текстовых токенов. –

+0

Массив целых или текстовых токенов ... которые как-то разграничены? Я хочу сказать, что в любом формате, который вы выбрали для использования, вполне реально хранить данные в одном поле в БД, если ваш язык запросов поддерживает оптимизированный способ доступа к данным. Поэтому мне кажется, что вы на самом деле соглашаетесь :) Я доволен запятой, потому что мои выбранные методы индекса могут обрабатывать строки с разделителями-запятыми быстрее, чем другие структуры в этом формате одного поля. –

+1

Это не форум для дискуссий, но не разделительный - хранится как соответствующий структурированный тип. Все это в текст - последнее средство. http://www.postgresql.org/docs/current/static/datatype.html –

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