Сведения о вопросе

Getthesound

20:55, 12th August, 2020

Теги

Рекомендуемый SQL дизайн базы данных для тегов или меток

Просмотров: 511   Ответов: 6

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

Я пропустил лучшую практику для тегов?



  Сведения об ответе

JUST___

14:16, 4th August, 2020

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

Table: Item
Columns: ItemID, Title, Content

Table: Tag
Columns: TagID, Title

Table: ItemTag
Columns: ItemID, TagID


  Сведения об ответе

park

01:10, 27th August, 2020

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

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

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

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

Это имеет некоторые основные преимущества:

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

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

Все теги для одного элемента:

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

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


  Сведения об ответе

piter

06:59, 17th August, 2020

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

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

Выполнение этого действия с помощью команды group=true сгруппирует результаты по имени тега и даже вернет количество встреченных тегов. Это очень похоже на подсчет встречаемости слова в тексте .


  Сведения об ответе

прога

19:28, 7th August, 2020

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

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

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


  Сведения об ответе

FAriza

19:06, 23rd August, 2020

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

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


  Сведения об ответе

ASSembler

17:45, 7th August, 2020

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

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться