2008-08-21 1 views
244

Я слышал о нескольких способах реализации тегов; используя таблицу сопоставления между TagID и ItemID (имеет смысл для меня, но делает ли он масштаб?), добавляя фиксированное количество возможных столбцов TagID к ItemID (кажется плохой идеей), сохраняя теги в текстовом столбце, разделенном запятой (звучит сумасшедший, но может работать). Я даже слышал, что кто-то порекомендовал разреженную матрицу, но тогда как имена тегов грациозно растут?Рекомендуемая конструкция базы данных SQL для тегов или тегов

Не хватает ли лучшей практики для тегов?

+7

Хорошо, это вопрос # 20856, (почти) тот же вопрос # 48475 спросил по крайней мере две недели после того, как этот вопрос был задан. – dlamblin 2008-10-07 16:02:38

+6

Еще один интересный вопрос: «Как SO реализует теги?» – Mostafa 2011-11-28 19:19:35

+1

Еще один интересный вопрос: «Не могли бы вы интернационализировать их, и если да, то как?» – DanMan 2013-12-03 11:14:51

ответ

353

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

Table: Item 
Columns: ItemID, Title, Content 

Table: Tag 
Columns: TagID, Title 

Table: ItemTag 
Columns: ItemID, TagID 
+10

Я не думаю, что это может быть достаточно. Это, безусловно, лучший способ сделать это. – BobbyShaftoe 2008-12-23 02:43:59

+98

Ясно? Где доказательства того, что это, безусловно, лучший способ сделать это (кроме того, что он нормализован - также, помните, что нормализация - это быстрые вставки, медленные выборы). – 2008-12-23 22:45:39

7

Я всегда хранил теги в отдельной таблице, а затем имел таблицу сопоставлений. Конечно, я никогда не делал ничего в действительно больших масштабах.

Наличие таблицы «тегов» и таблицы карт делает довольно тривиальным создание облаков тегов &, так как вы можете легко собрать SQL, чтобы получить список тегов с подсчетом того, как часто используется каждый тег.

11

Используйте один форматированный текстовый столбец [1] для хранения тегов и используйте способную полнотекстовую поисковую систему для индексации этого. Иначе вы столкнетесь с проблемами масштабирования при попытке реализовать логические запросы.

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

[1] Некоторые РСУБД даже предоставляют собственный тип массива, который может быть даже лучше подходит для хранения, не нуждаясь в синтаксическом анализе, но может вызвать проблемы с полным текстовым поиском.

37

Если вы используете базу данных, поддерживающую сокращение по карте, например couchdb, сохранение тегов в текстовом поле или в поле списка действительно лучший способ. Пример:

tagcloud: { 
    map: function(doc){ 
    for(tag in doc.tags){ 
     emit(doc.tags[tag],1) 
    } 
    } 
    reduce: function(keys,values){ 
    return values.length 
    } 
} 

Запуск этого с группой = TRUE будет группа результатов по имени тега, и даже возвращать подсчет количества раз, что тег сталкивался. Он очень похож на counting the occurrences of a word in text.

57

Обычно я согласен с Яковом Ellis, но в этом особом случае существует еще один жизнеспособное решение:

Используйте две таблицы:

Table: Item 
Columns: ItemID, Title, Content 
Indexes: ItemID 

Table: Tag 
Columns: ItemID, Title 
Indexes: ItemId, Title 

Это имеет ряд существенных преимуществ:

Сначала это делает разработка намного проще: в трехэтажном решении для вставки и обновления item вам нужно найти таблицу Tag, чтобы увидеть, есть ли уже записи. Тогда вы должны присоединиться к ним с новыми. Это не тривиальная задача.

Затем он делает запросы проще (и, возможно, быстрее). Будут три основных запроса к базе данных, которые вы сделаете: Выведите все Tags за один Item, нарисуйте облако тегов и выберите все элементы для одного заголовка тега.

Теги для одного пункта:

3-Table:

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 

Tag-Cloud:

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: Я бы выбрал решение с двумя столами. (. На самом деле я собираюсь я нашел эту статью, чтобы увидеть, если есть веские аргументы против него.)

0

Я хотел бы предложить следующую конструкцию: элемента таблицы: Itemid, taglist1, taglist2
это будет быстро и упростить сохранение и извлечение данных на уровне позиции.

В параллельной сборки другой таблицы: Метки теги не делают теги уникальный идентификатор, и если вы бежите из пространства во 2-й колонке, которая содержит позволяет сказать 100 элементов создать еще одну строку.

Теперь при поиске элементов для тега будет очень быстро.

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