Структура таблицы соединений для тегов - PullRequest
1 голос
/ 18 июля 2009

Я работаю над небольшим программным обеспечением для блогов, и мне бы хотелось, чтобы к сообщению были прикреплены теги. Каждое сообщение может содержать от 0 до бесконечных тегов, и мне интересно, возможно ли это сделать без объединения таблиц?

Поскольку количество тегов не ограничено, я не могу просто создать n полей (от Tag1 до TagN), поэтому другой подход (который, по-видимому, и использует StackOverflow) - это использовать одно большое текстовое поле и разделитель, т.е. <Вкладка3>».

Проблема в том, что: если я хочу отображать все сообщения с тегом, мне нужно будет использовать оператор «Like '% %'», и они могут AFAIK не использовать индексы, требующие полного сканирования таблицы .

Есть ли подходящий способ решить эту проблему?

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

Ответы [ 4 ]

6 голосов
/ 18 июля 2009

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

3 голосов
/ 18 июля 2009

Отдельная таблица тегов - действительно единственный путь. Это единственный способ разрешить бесконечное количество тегов.

2 голосов
/ 18 июля 2009

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

Posts:
PostID  | PostTitle    | PostBody          | PostAuthor
--------+--------------+-------------------+-------------
1146044 | Join-Free... | I'm working on... | Michael Stum

Tags:
TagID | TagName
------+-------------
1     | Archetecture

PostTags:
PostID  | TagID
--------+------
1146044 | 1 

Тогда вы можете добавить столбцы для оптимизации ваших запросов. Если бы это был я, я бы просто оставил таблицы Posts и Tags в покое и добавил бы дополнительную информацию в таблицу соединений PostTags. Конечно, то, что я добавлю, может немного зависеть от запросов, которые я собираюсь выполнить, но, вероятно, я бы по крайней мере добавил Posts.PostTitle, Posts.PostAuthor и Tags.TagName, так что мне нужно выполнить только два запроса для отображения блога сообщение,

SELECT * FROM `Posts` WHERE `Posts`.`PostID` = $1 
SELECT * FROM `PostTags` WHERE `PostTags`.`PostID` = $1

А для суммирования всех постов по данному тегу требуется еще меньше

SELECT * FROM `PostTags` WHERE `PostTags`.`TagName` = $1

Очевидно, что недостатком денормализации является то, что вам нужно проделать немного больше работы, чтобы поддерживать денормализованные таблицы в актуальном состоянии. Типичный способ справиться с этим - установить некоторые проверки работоспособности в вашем коде, которые обнаруживают, когда денормализованный запрос не синхронизирован, путем сравнения его с другой информацией, которая оказывается доступной. Такая проверка может пойти в приведенном выше примере, сравнивая заголовки записей в наборе результатов PostTags с заголовками в результате Posts. Это не вызывает дополнительный запрос. В случае несоответствия программа может уведомить администратора, т. Е. Зарегистрировать несоответствие или отправить электронное письмо.

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

0 голосов
/ 18 июля 2009

Если вы используете SQL Server, вы можете использовать одно текстовое поле (varchar (max) кажется подходящим) и полнотекстовое индексирование. Затем просто выполните полнотекстовый поиск по тегу, который вы ищете.

...