Зазвичай я погоджуюся з Яаковим Еллісом, але в цьому спеціальному випадку є ще одне життєздатне рішення:
Використовуйте дві таблиці:
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: Я б пішов на рішення двох столів. (Насправді я збираюся. Я знайшов цю статтю, щоб побачити, чи є вагомі аргументи проти неї.)