FULLTEXT or FOREIGN KEY

GHopper

Новичок
FULLTEXT or FOREIGN KEY

Здравствуйте!
БД mysql5. Разрабатываю структуру для сайта новостей.

PHP:
DROP TABLE IF EXISTS `news`;
DROP TABLE IF EXISTS `counters`;

CREATE TABLE `counters` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `news_id` INT UNSIGNED NOT NULL,
  `cnt_day` INT UNSIGNED DEFAULT 0,
  `cnt_month` INT UNSIGNED DEFAULT 0,
  `cnt_all` INT UNSIGNED DEFAULT 0,
  PRIMARY KEY (`id`),
  CONSTRAINT `counter_fk` FOREIGN KEY (news_id) REFERENCES news(id) ON DELETE CASCADE
) ENGINE=INNODB;


CREATE TABLE `news` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `header` VARCHAR(500),
  `subheader` VARCHAR(500),
  `leed` TINYTEXT,
  `text` TEXT NOT NULL,
  `src_name` VARCHAR(256),
  `src_url` VARCHAR(256),
  `ya_title` VARCHAR(500),
  `dt` TIMESTAMP,
  `ready` BOOL DEFAULT FALSE,
  `cat_id` INT UNSIGNED NOT NULL,
  `user_id` INT UNSIGNED NOT NULL,
  `city_id` INT UNSIGNED,
  /*FULLTEXT (header,subheader,leed,text),*/
  PRIMARY KEY (`id`),
  CONSTRAINT `cat_fk` FOREIGN KEY (cat_id) REFERENCES cat(id),
  CONSTRAINT `user_fk` FOREIGN KEY (user_id) REFERENCES user(id),
  CONSTRAINT `city_fk` FOREIGN KEY (city_id) REFERENCES city(id)

) ENGINE=INNODB;
Таблица news - новости, counters - счетчик просмотров новостей. Все хорошо, только вот в таблице news мне очень хочется использовать полтотекстный поиск. Для этого мне нужно эту таблицу преобразовать в MyISAM, но это нарушит правило для внешних ключей - все табилци должны быть INNODB!

Как решить мою проблему?

Если-же FULLTEXT`у существовать в такой структуре БД не дано, то как его заменить? Как организовать поиск с учетом релевантности без FULLTEXT? Какова потеря в скорости rlike по сравнению с FULLTEXT?
Может все-таки целесообразней для моих нужд все-таки заменить FK на триггеры и уйти к MyISAM и FULLTEXT? Но в документации описание InnoDB Storage Engine мне понравилось больше, чем MyISAM...
 

Wicked

Новичок
Какова потеря в скорости rlike по сравнению с FULLTEXT?
какова потеря скорости между аналогичными запросами, один из которых использует индексы, а другой - нет?

Для этого мне нужно эту таблицу преобразовать в MyISAM
Часто делают просто MyISAM-дубликат InnoDB-таблицы. Такое нарушение не будет фатальным.

PS: есть еще один вариант сделать полнотекстовый поиск: InnoDB + SphinxSE ( http://www.sphinxsearch.com/doc.html#sphinxse )
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
А что мешает перейти на PostgreSQL, где можно одновременно использовать внешние ключи и полнотекстовые индексы?
 

Dagdamor

Новичок
Sad Spirit
В Pg есть fulltext? Кинь ссылочку на описание и примеры плиз.
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: Dagdamor
Sad Spirit
В Pg есть fulltext? Кинь ссылочку на описание и примеры плиз.
Full Text Search в документации 8.3
До 8.3 имеет чуть меньше возможностей (только индексы GiST) и не встроен в сервер, а подключается из contrib модуля. Но ведь славных пользователей MySQL не напугать contrib'ами, у них даже модули работы с данными на физическом уровне так подключаются.
 

Dagdamor

Новичок
Sad Spirit
Ммм... это та самая версия, в которой не работает UTF-8?
 

GHopper

Новичок
Автор оригинала: Wicked
какова потеря скорости между аналогичными запросами, один из которых использует индексы, а другой - нет?


Часто делают просто MyISAM-дубликат InnoDB-таблицы. Такое нарушение не будет фатальным.

PS: есть еще один вариант сделать полнотекстовый поиск: InnoDB + SphinxSE ( http://www.sphinxsearch.com/doc.html#sphinxse )
1. а что мешает rlike искать по индексу?
2. в моем случае мне нужно делать MyISAM-дубликат таблици, в которой хранится текст всех новостей! Это значит, что база данных вырастит в два раза (остальными таблицами можно пренебречь, т.к. они значительно меньше)! Я считаю это не слишком рациональным выходом.
3. InnoDB + SphinxSE - возможно это выход, но вот наш системный администратор сказал: "Думаю, что перекомпилировать исходники каждый раз при обновлении MySQL - это гемор". Да и при переходе на чужой хостинг будут пироги.

В моем случае расширеный поиск - не ключевой момент. Гораздо важнее стабильность и скорость выборки. Как то ведь работают форумы на InnoDB и используют поиск по релевантности... как?
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: Dagdamor
Sad Spirit
Ммм... это та самая версия, в которой не работает UTF-8?
А шо ви таки хотите от пеrвой беты?..

Я ж давал уже ссылку на разработчиков, отсутствие UTF-8 в винде --- это известная проблема, которую во второй бете обещают исправить.
 

Gas

может по одной?
GHopper
1. like - это не поиск в приципе.
2. "база данных вырастит в два раза", допустим - 100 новостей в день по 2KB, и за 5 лет имеем ~ 400MB текстовых данных. Оверхед на хранение в myisam + индекс увеличат размер до 3-х раз. При нынешней стоимости гигабайта это вообще не проблема. Тут ключевой фактор скорость поиска и fulltext на таком объёме я бы не юзал именно по этой причине. Если такой обьём не предпологается, то дублирование текстовых данных в myisam вполне себе вариант.
3. InnoDB + Sphinx - самый правильный конечно, только не обязательно ставить SphinxSE storage engine к Mysql, его можно использовать и как внешнюю утилиту без перекомпиляции mysql. Хотя если планируется серьёзный проект, то проблем и сомнений вида "Думаю, что перекомпилировать исходники каждый раз при обновлении MySQL - это гемор. Да и при переходе на чужой хостинг будут пироги." вообще не должно возникать.
 

Krishna

Продался Java
Gas
Fulltext поиск по сотне-другой мегабайт для нормального сервера - не проблема.
 

GHopper

Новичок
Автор оригинала: Gas
GHopper
1. like - это не поиск в приципе.
2. "база данных вырастит в два раза", допустим - 100 новостей в день по 2KB, и за 5 лет имеем ~ 400MB текстовых данных. Оверхед на хранение в myisam + индекс увеличат размер до 3-х раз. При нынешней стоимости гигабайта это вообще не проблема. Тут ключевой фактор скорость поиска и fulltext на таком объёме я бы не юзал именно по этой причине. Если такой обьём не предпологается, то дублирование текстовых данных в myisam вполне себе вариант.
3. InnoDB + Sphinx - самый правильный конечно, только не обязательно ставить SphinxSE storage engine к Mysql, его можно использовать и как внешнюю утилиту без перекомпиляции mysql. Хотя если планируется серьёзный проект, то проблем и сомнений вида "Думаю, что перекомпилировать исходники каждый раз при обновлении MySQL - это гемор. Да и при переходе на чужой хостинг будут пироги." вообще не должно возникать.
1. я говорил про rlike, который может искать по индексу (как FULLTEXT) длинной до 767 байт (для InnoDB, а в MyISAM, насколько мне известно, он может быть до 1000 байт). Что будет работать быстрее rlike на InnoDB или MATCH ... AGAINST на MyISAM?
2. Один из основных принципов проектирования БД - исключение избыточности! Я могу понять, что мы храним два одинаковых столбца типа INT в разных таблицах, чтобы упростить запросы и уменьшить время поиска, но вот дублировать ТАБЛИЦЫ огромных размеров... имхо неправильно это. Но, как вариант, это пока самый приемлемый выход.

И все-же! Какие идею будут у многоуважаемых знатоков по поводу того, как можно выбрать данные из InnoDB с учетом релевантности? Неужели нету механизма, способного заменить MATCH ... AGAINST для InnoDB? Пусть он будет абсурдным, пусть он будет неоправданно долгим... но ПУСТЬ ОН БУДЕТ!

Мы не пытаемся убедить друг друга в том, что PostgreSQL круче MySQL, что SphinxSE рулит и что место на диске жать не надо. Мы просто ищем возможные решения задачи для конкретной БД с рассмотрением всех возможных вариантов. После чего каждый сам должен для себя сделать соответственные выводы...
 

Krishna

Продался Java
я говорил про rlike, который может искать по индексу (как FULLTEXT) длинной до 767 байт
Fulltext индексы и обычные индексы, по которым может искать like (rlike - неважно) - это абсолютно разные вещи.

Полнотекстовый индекс разбивает текст на слова и хранит количества их вхождений в тексте. (На пальцах должно быть так, конкретная реализация мне неизвестна)
Обычный индекс строк лишь сортирует строки на манер чисел и строит B-дерево для быстрого поиска разных значений. Как результат обычный строчный индекс может применяться лишь при известном начале строки.

-~{}~ 18.10.07 07:42:

Собственно, поддержка полнтотекстового поиска в MyISAM наличествует, в отличие от InnoDB, именно потому, что в MyISAM имеются полнотекстовые индексы, а в InnoDB - нет.
 

GHopper

Новичок
и еще один неприятный для InnoDB момент:

в таблице myisam 8779 записей. Выбираем через MATCH ... AGAINST

PHP:
SELECT * FROM news_articles where MATCH (header,subheader,leed,text,keywords) AGAINST ('book');
explain показывает, что число задействованных в поиске строк равно числу строк в результате поиска. Кул!

Теперь пытаемся найти аналог MATCH ... AGAINST - RLIKE

PHP:
SELECT * FROM news_articles where header REGEXP '^a'
explain показывает, что число задействованных строк в поиске равно 8779, тоесть происходит полное сканирование таблицы (результат - всего пять запсей)! Неприемлемый вариант (


Все это наводит на мысли, что использование InnoDB неприемлемо в моем случе, но какже красивые слова из офф. документации на MySQL

InnoDB provides MySQL with a transaction-safe (ACID compliant) storage engine that has commit, rollback, and crash recovery capabilities. InnoDB does locking on the row level and also provides an Oracle-style consistent non-locking read in SELECT statements. These features increase multi-user concurrency and performance. There is no need for lock escalation in InnoDB because row-level locks fit in very little space. InnoDB also supports FOREIGN KEY constraints.
bla-bla-bla
InnoDB is used in production at numerous large database sites requiring high performance. The famous Internet news site Slashdot.org runs on InnoDB. Mytrix, Inc. stores over 1TB of data in InnoDB, and another site handles an average load of 800 inserts/updates per second in InnoDB.
В адрес MyISAM таких слов сказано небыло...
 

Wicked

Новичок
Автор оригинала: GHopper
1. я говорил про rlike, который может искать по индексу (как FULLTEXT) длинной до 767 байт (для InnoDB, а в MyISAM, насколько мне известно, он может быть до 1000 байт).
Ни разу не слышал о том, что rlike ВООБЩЕ может использовать индексы, не говоря уже об использовании индексов, чтобы сделать полнотекстовый поиск. Если уж обычный like сильно в этом ограничен (о чем сказал HRAKK), то на rlike вообще в этом плане даже надежды быть не может.

2. Один из основных принципов проектирования БД - исключение избыточности!
Знать, как делать правильно, всегда полезно. В то же время есть такая штука, как реальный мир, в котором это не работает.

И все-же! Какие идею будут у многоуважаемых знатоков по поводу того, как можно выбрать данные из InnoDB с учетом релевантности? Неужели нету механизма, способного заменить MATCH ... AGAINST для InnoDB? Пусть он будет абсурдным, пусть он будет неоправданно долгим... но ПУСТЬ ОН БУДЕТ!
Да пожалуйста. Вы можете самостоятельно сделать инверсный индекс -- таблицу, в которой будет прописано, в какой новости какие слова в каком кол-ве встречаются.
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: GHopper
Мы не пытаемся убедить друг друга в том, что PostgreSQL круче MySQL, что SphinxSE рулит и что место на диске жать не надо. Мы просто ищем возможные решения задачи для конкретной БД с рассмотрением всех возможных вариантов. После чего каждый сам должен для себя сделать соответственные выводы...
Тебе уже кинули 3 возможных варианта:
1) Дублировать таблицу в MyISAM
2) Использовать Sphinx
3) Перейти на Postgres (в котором, в отличие от, можно реализовать поиск с русской морфологией):
Код:
test=# select to_tsvector('Мы просто ищем возможные решения задачи для конкретной БД с рассмотрением всех возможных вариантов. После чего каждый сам должен для себя сделать соответственные выводы...');
                                                                                        to_tsvector                                                             
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 'бд':9 'вывод':24 'задача':6 'искать':3 'каждый':17 'вариант':14 'должный':19 'простой':2 'решение':5 'сделать':22 'возможный':4,13 'конкретный':8 'рассмотрение':11 'соответственный':23
(1 запись)
А ты в ответ ломаешься как шестнадцатилетняя девственница --- варианты, видите ли, не нравятся.

Ну если не нравятся, то тогда только вариант Wicked'а --- самостоятельно делать инверсный индекс, вроде того как у phpBB унутрях.
 

GHopper

Новичок
может кто-нибудь посоветует бесплатную систему морфологического разбора русского языка?
 

GHopper

Новичок
поковырял в phpbb - не образец для подражания! разбивает текст на слова и их заносит в БД не меняя словоформы! В итоге ни тебе морфологического поиска, ни тебе релевантности (т.к. он ее не высчитывает для конкретного поста). Да и размер БД сильно увеличивается.

Принял решение, что нужно все делать самому. Проблема - морфологический разбор слов или выбор алгоритма стемминга. В своих поисках наткнулся на ресурс , который мне очень помог! Теперь у моего новостного портала есть таблица с текстом новости, таблица с базой первоформ слов и таблица, в которой хранятся первоформы слов из текста новости со значением релевантности. Оператор like нигде не используется!

[news]
id, text

[word]
id, word

[search]
id, news_id, word_id, relevant

Как вам мое решение? Кто увидел грабли или может предложить улучшение?
 

Wicked

Новичок
дублировать таблицу в myisam, ему, видите ли, места жалко. А тратить непонятно сколько на инверсный индекс - это всегда пожалуйста.
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: GHopper
Как вам мое решение? Кто увидел грабли или может предложить улучшение?
Процедурный вопрос: нахрена в таблице search поле id?

Ну а так с пивом пойдёт, вот добавишь учёт позиций слова в документе, разные веса для разных частей документа (загойловок новости должен быть важнее собственно текста), сортировку по релевантности, подсветку найденных слов и через полгода-год догонишь по функциональности нынешний полнотекстовый поиск PostgreSQL. По скорости не догонишь конечно, ибо язык Ц несколько быстрее языка ПоХаПэ, да и специализированный инверсный индекс несколько быстрее его эмуляции.
 
Сверху