Должен ли я оставить структуру данных такой, какая она есть? Если да, то как мне структурировать sql, чтобы разрешить полнотекстовый поиск по всем трем столбцам - title, desc и tag?
Это было бы невозможно. Индексы могут охватывать только столбцы одной таблицы.
Или было бы предпочтительнее просто избавиться от keysTable и иметь фактические теги через запятую в столбце «теги» в dataTable?
Это, безусловно, самое простое решение. В настоящее время вы не получаете никакой выгоды от присвоения тегам собственной идентификации, поскольку вы не можете использовать внешние ключи и индексировать их.
Однако индексация FULLTEXT в MySQL не идеальна для системы тегов:
- по умолчанию, он не будет индексировать слова короче четырех букв;
- по умолчанию у него есть много (много) стоп-слов, которые он не будет индексировать, которые вы, возможно, захотите использовать для тегов;
- это будет менее эффективно, чем обычный индекс;
- он работает только в MyISAM, который во всех других отношениях намного хуже, чем InnoDB. За исключением случаев, когда вам действительно нужно, вы не должны использовать MyISAM сегодня.
Вы можете исправить минимальную длину слова и стоп-слова, изменив конфигурацию MySQL. Это сделает ваши индексы намного больше, хотя. Это может быть приемлемым решением, если вы управляете базой данных везде, где будет развернуто ваше приложение, и если вы используете теги как «дополнительные слова» в полнотекстовом поиске, а не в полной системе категоризации.
В противном случае ... разделенные запятыми все в базе данных подозрительно IMO. Обычно лучше использовать таблицу соединений «один ко многим», чтобы выразить идею о том, что у одного объекта есть много тегов. Затем вы можете использовать простой индекс для облегчения поиска вместо ограниченной схемы индексации FULLTEXT, которая будет быстрее, надежнее и позволит вам использовать InnoDB и внешние ключи. eg.:
dataTable
ID (primary key)
title
desc
dataTags
ID (foreign key -> dataTable)
tagName (index this column)
(Вы могли бы по-прежнему иметь отображение tagID-> tagName, если вы хотите, чтобы теги имели независимую идентификацию. Хотя я не уверен, что это делает что-то полезное в вашем случае.)
Если вам нужно получить список через запятую из отношения «один ко многим», как описано выше, вы можете сделать это с помощью специфичной для MySQL функции GROUP_CONCAT .
SELECT dataTable.*, GROUP_CONCAT(dataTags.tagName)
FROM dataTable
JOIN dataTags ON dataTags.ID=dataTable.ID
GROUP BY dataTable.ID;
Это оставляет полнотекстовое индексирование заголовка и деск. К сожалению, вам нужно поместить их в таблицу MyISAM.
Распространенной альтернативой этому, которую вы также можете рассмотреть, будет сохранение «канонических» копий в основной таблице (потенциально в ACID-безопасной таблице InnoDB) и хранение отдельной копии всех заголовков, дескрипторов и тегов. вместе в индексируемой FULLTEXT таблице MyISAM исключительно для приманки полнотекстового поиска. Это означает, что вам нужно делать дополнительное обновление каждый раз, когда вы изменяете первичные данные (хотя, если вам не удастся или придется откатить транзакцию, по крайней мере, это только относительно неважная поисковая приманка, которая сейчас не так), но преимущество в том, что вы можете применить дополнительная обработка к нему, такая как обработка стеков и знаков препинания, которую индексатор MySQL FULLTEXT не выполняет сам.