У меня есть несколько скриптов CURL, которые собирают данные со многих внутренних сайтов компании в общую базу данных. Каждый скрипт называется «экземпляром». Данные добавляются в базу данных в виде записей. Каждая запись имеет несколько «полей», которые представляют собой пару ключ-> значение. Поскольку клавиши для каждой записи являются динамическими и могут быть любыми (даже в одном экземпляре), они не жестко закодированы в таблице MySQL.MySQL запросы с MATCH и AGAINST подвешивание
Так есть эти таблицы:
- записи - содержат список записей, каждая из которых связана с экземпляром
- record_fields - содержит список полей, связанных с записью
- record_fields_labels - в основном список этикеток. Это сохраняется в базе данных для экономии места (т. Е. Вместо полей record_fields есть тысячи полей, которые имеют метку «Дата статьи», все они будут иметь номер 8, который является идентификатором записи в record_labels, которая имеет «Дата статьи» «как его ценность».
record_fields и record_fields_labels оба MyISAM таблицы с индексом FULLTEXT на «содержание» (столбец в record_fields, который содержит фактические данные) и «ярлык» (столбец в record_fields_labels, который имеет имя метки).
База данных содержит миллионы записей - для каждого умножить количество полей записи ... Когда экземпляры бежать, чтобы проверить, существует ли уже запись в базе данных, они делают следующий SQL-запрос:
SELECT r.id FROM records r INNER JOIN record_fields rf ON rf.record_id=r.id INNER JOIN record_fields_labels as rfl ON rf.label=rfl.id WHERE r.instance IN (120) AND MATCH (rf.content) AGAINST ('"http://xxxx.xxxx/xxx.xxx.xxx"' IN BOOLEAN MODE) AND MATCH (rfl.label) AGAINST ('"Article URL"' IN BOOLEAN MODE) GROUP BY r.id
В этом примере http://xxxx.xxxx/xxx.xxx.xxx - это URL-адрес статьи, скрипт проверяет, существует ли она в системе.
TL; DR
Проблема заключается в следующем: когда база данных огромна (т.е. миллионы записей/полей записи) - выше запрос просто вешает трубку. Запрос будет работать, даже в течение нескольких часов, без видимых причин. Этот же запрос используется для поиска элементов в собранных данных и, похоже, работает (или работал до недавнего времени).
Все, что я хочу, это показать, существует ли такая запись или нет. Это не проблема индексирования, а что-то особенное, что нужно делать с MATCH AGAINST. Я предпочитаю избегать добавления дополнительного индекса всего содержимого (в дополнение к индексу FULL TEXT) для экономии места.
Кто-нибудь знает, что вызывает эту проблему?
Благодаря
Вы запустили 'EXPLAIN' на своем SQL, чтобы увидеть, как запрос запускается движком? – syck
И: как правило, разумно сконструированный индекс является наиболее эффективным способом найти что-либо или доказать его существование. Это для чего. – syck