Задать вопрос
samorez999
@samorez999

Проблема с пониманием проектирования бд, поможете?

Есть у меня большая таблица, назовем ее "объявления". Нужно одному "объявлению" назначить несколько "тегов".

Вот мой ход мыслей:
Создать отдельную таблицу "теги" и перечислить первичные ключи в колонке "теги" первой таблицы. Но перечисление нарушает 1NF.
Создать таблицу типа многие-ко-многим "объявления-теги", но там будет плодиться очень много значений после каждой вставки "объявления".
Можно перечислять теги просто строкой в поле.

Как это делается в реальных проектах?
  • Вопрос задан
  • 149 просмотров
Подписаться 1 Простой 8 комментариев
Решения вопроса 2
к примеру, у одного объявления в среднем 3 тега, на 1 миллион объявлений будет 3 миллиона записей в "объявления-теги", как там будет по скорости при выборке? Сильно я выиграю, если нарушу правило и буду писать теги, перечисляя их в строку через запятую?

1. Представим, что промежуточная таблица объявление-тег - это два гуида.
Тогда одна строчка будет занимать около 32 байт. 3*32*1000000 = 96 мегабайт (метрических)
2. Естественно, выборка будет медленной, если не добавить индекс. Индекс по id объявления ещё примерно столько же займёт. Выборка уже будет быстрее. Для фильтров ещё надо будет добавить индекс в обратную сторону - от id тега.
3. Ещё и фильтроваться по тегам можно будет, что, мне кажется, является одним из важнейших качеств тегов.
4. Если 96 мегабайт тебя пугает - используй int64 или int32 - тогда будет меньше в 2 или в 4 раза соответственно
Сильно я выиграю, если нарушу правило и буду писать теги, перечисляя их в строку через запятую?

Как уже сказали в комментах - очень сильно обосрёшься.
Выборка, конечно, будет очень быстрая, но
1. Представим что тег - это 6 букв на русском языке, а храним мы строки в Utf8 кодировке.
Тогда на каждое объявление будет тратиться 6*2*3+3+4=45 байт. Соответственно на миллион объявлений уйдёт 45 метрических мегабайт.
2. Но тут не будет индексов, по тому и фильтроваться будет очень дорого

PS: все прикидки по памяти взяты с потолка. В реальной БД числа будут другие, но примерно похожие.
PPS: если не совсем понятно, что я предлагаю, то вот:
._________.             .______________.           .____________.
| post    |             | post_tag     |           | tag        |
|=========|             |==============|           |============|
| id: int |<------------| post_id: int |           | id: int    |
| ...     |             | tag_id: int  |---------->| name: text |
|_________|             |______________|           |____________|
Ответ написан
justhabrauser
@justhabrauser
IT specialist
> Создать таблицу типа многие-ко-многим "объявления-теги", но там будет плодиться очень много значений после каждой вставки "объявления"

Что значит "много"? Столько, сколько тегов у объявления. Ни больше, ни меньше.
По 2…16 байт на один тег для одного объявления, как выше написали.
Меньше только если не использовать теги.
И объявления.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@Drno
я вообще не эксперт по БД, но может создать отдельную таблицу для тегов... перечислить их там
далее добавить поле\поля к объявлению и там уже помечать. типо 1 есть тег, 0 нет тега... и так по каждому
Ответ написан
tsklab
@tsklab
Здесь отвечаю на вопросы.
Использование для тегов отдельной таблицы — правильное решение.
Но не всё так однозначно. Использование списка тоже возможно и имеет свои преимущества. Например, на хабре используется отдельная таблица и нет возможности добавить свой уточняющий тег для вопроса. На других web2 можно добавить в список свой. По поводу страха перед удалением и переименованием: на хабре когда-нибудь удаляли тег? А как давно переименовывали?
Использование списков поддерживает множество СУБД, а некоторые имею специальный тип данных.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы