Обычно я согласен с Яаковом Эллисом, но в этом особом случае есть другое жизнеспособное решение:
Используйте две таблицы:
Table: Item
Columns: ItemID, Title, Content
Indexes: ItemID
Table: Tag
Columns: ItemID, Title
Indexes: ItemId, Title
Это имеет несколько основных преимуществ:
Во-первых, это значительно упрощает разработку: в решении с тремя таблицами для вставки и обновления item
вы должны просмотреть Tag
таблицу, чтобы увидеть, есть ли уже записи. Тогда вы должны присоединиться к ним с новыми. Это не тривиальная задача.
Тогда это делает запросы проще (и, возможно, быстрее). Вам нужно выполнить три основных запроса к базе данных: вывести все Tags
для одного Item
, нарисовать облако тегов и выбрать все элементы для одного заголовка тега.
Все теги для одного элемента:
3-таблица:
SELECT Tag.Title
FROM Tag
JOIN ItemTag ON Tag.TagID = ItemTag.TagID
WHERE ItemTag.ItemID = :id
2-Таблица:
SELECT Tag.Title
FROM Tag
WHERE Tag.ItemID = :id
Облако тегов:
3-таблица:
SELECT Tag.Title, count(*)
FROM Tag
JOIN ItemTag ON Tag.TagID = ItemTag.TagID
GROUP BY Tag.Title
2-Таблица:
SELECT Tag.Title, count(*)
FROM Tag
GROUP BY Tag.Title
Предметы для одного тега:
3-таблица:
SELECT Item.*
FROM Item
JOIN ItemTag ON Item.ItemID = ItemTag.ItemID
JOIN Tag ON ItemTag.TagID = Tag.TagID
WHERE Tag.Title = :title
2-Таблица:
SELECT Item.*
FROM Item
JOIN Tag ON Item.ItemID = Tag.ItemID
WHERE Tag.Title = :title
Но есть и некоторые недостатки: это может занять больше места в базе данных (что может привести к увеличению количества дисковых операций, что медленнее), и это не нормализуется, что может привести к несоответствиям.
Аргумент размера не так силен, потому что сама природа тегов заключается в том, что они обычно довольно малы, поэтому увеличение размера невелико. Можно утверждать, что запрос для заголовка тега намного быстрее в небольшой таблице, которая содержит каждый тег только один раз, и это, безусловно, верно. Но если принять во внимание экономию, связанную с отсутствием необходимости присоединения, и тот факт, что вы можете построить для них хороший индекс, это может легко компенсировать это. Это, конечно, сильно зависит от размера базы данных, которую вы используете.
Аргумент о несостоятельности тоже немного спорный. Теги являются свободными текстовыми полями, и нет ожидаемой операции, такой как «переименовать все теги« foo »в« bar »».
Итак tldr: я бы пошел на решение двух столов. (На самом деле я собираюсь. Я нашел эту статью, чтобы увидеть, есть ли веские аргументы против этого.)