Я разрабатываю большой контент-сайт с табличным «содержимым» с более чем 50 миллионами записей. Вот структура таблицы:
contain id(INT11 INDEX), name(varchar150 FULLTEXT), description (text FULLTEXT), date(INT11 INDEX)
Я хочу добавить «теги» к этому содержимому.
Я думаю, 2 метода:
Создайте столбец «тег» varchar (255 FULLTEXT) в содержимом таблицы. Храните все теги, разделенные comas, и найдите строку за строкой (что, я думаю, будет медленным), используя MATCH & AGAINS.
Сделайте 2 таблицы. Первое имя таблицы «теги» с идентификаторами столбцов, тегом (varchar (30 INDEX или FULLTEXT?)), «Content_tags» с id, tag_id (int11 INDEX) и content_id (int11 INDEX) и содержимым поиска по JOINS из 3 таблиц (содержимое – contents_tags – теги), чтобы получить все содержимое с помощью тега (ов).
Я думаю, что это медленное и убийство памяти, потому что ENORMOUS JOIN из 50M table * contents_tags * тегов.
Каков наилучший способ хранения тегов, чтобы сделать его максимально эффективным? Каков самый быстрый способ поиска по тексту (например, «фильм 3D 2011» и простой тег «видео») и найти содержимое.?
Размер таблицы (около 5 ГБ без тегов). Таблица – это MYISAM, потому что мне нужно сохранить имя и описание содержимого таблицы в FULLTEXT для строкового поиска (пользователи теперь ищут по этим полям), и вам нужна лучшая скорость для поиска по тегам.
Есть ли у вас опыт в этом?
Благодаря!
Индексы FULLTEXT на самом деле не так быстро, как вы думаете.
Используйте отдельную таблицу для хранения ваших тегов:
Table tags ---------- id integer PK tag varchar(20) Table tag_link -------------- tag_id integer foreign key references tag(id) content_id integer foreign key references content(id) /* this table has a PK consisting of tag_id + content_id */ Table content -------------- id integer PK ......
ВЫБРАТЬ весь контент с помощью тега x, используя:
SELECT c.* FROM tags t INNER JOIN tag_link tl ON (t.id = tl.tag_id) INNER JOIN content c ON (c.id = tl.content_id) WHERE tag = 'test' ORDER BY tl.content_id DESC /*latest content first*/ LIMIT 10;
Из-за внешнего ключа все поля в tag_links индивидуально индексируются.
`WHERE tags = 'test' выбирает 1 (!) Запись.
Equi-объединяет это с 10 000 taglinks.
И Equi-join объединяет 1 запись контента каждый (каждая tag_link только указывает на 1 контент).
Из-за ограничения 10 MySQL перестанет смотреть, как только у него будет 10 элементов, поэтому он действительно смотрит только на 10 записей tag_links.
Content.id – автоинкремент, поэтому более высокие номера – очень быстрый прокси для новых статей.
В этом случае вам не нужно искать что-либо иное, кроме равенства, и вы начинаете с 1 тега, который вы equi-join используете с помощью целых ключей (возможно быстрое соединение).
В этом случае нет if-thens-or-buts, это самый быстрый способ.
Обратите внимание, что, поскольку существует не более 1000 тегов, любой поиск будет намного быстрее, чем просмотр в полной таблице содержимого.
в заключение
Поля CSV – очень плохая идея, никогда не используйте ее в базе данных.