Заметка:
Так, как я полагал, реальная проблема связана с предложением IN, которое я использую для теги. Изменение части запроса для текстового поиска не помогло. Любая идея, как улучшить запрос?
Запрос выполняется слишком долго при работе на сервере. Здесь Partha S – это элемент поиска, введенный пользователем. Табличные контакты содержат личную информацию, теги содержат название и идентификатор категории; и таблица contacts2tags содержит contactid и tagid со значениями, аналогичными id в контактах и тегах соответственно.
SELECT * FROM ( SELECT *, IF ( first_name LIKE 'Partha S' OR last_name LIKE 'Partha S' OR phone_number LIKE 'Partha S' OR mobile_number LIKE 'Partha S' OR email_address LIKE 'Partha S' OR address LIKE 'Partha S' OR organization LIKE 'Partha S' OR other LIKE 'Partha S' OR sector LIKE 'Partha S' OR designation LIKE 'Partha S' OR concat ( first_name, ' ', last_name ) LIKE 'Partha S' OR concat ( last_name, ' ', first_name ) LIKE 'Partha S', 1, 0 ) as exact, IF ( ( first_name LIKE '%Partha%' OR last_name LIKE '%Partha%' OR phone_number LIKE '%Partha%' OR mobile_number LIKE '%Partha%' OR email_address LIKE '%Partha%' OR address LIKE '%Partha%' OR organization LIKE '%Partha%' OR other LIKE '%Partha%' OR sector LIKE '%Partha%' OR designation LIKE '%Partha%' ) AND ( first_name LIKE '%S%' OR last_name LIKE '%S%' OR phone_number LIKE '%S%' OR mobile_number LIKE '%S%' OR email_address LIKE '%S%' OR address LIKE '%S%' OR organization LIKE '%S%' OR other LIKE '%S%' OR sector LIKE '%S%' OR designation LIKE '%S%' ) , 1, 0 ) as normal FROM contacts WHERE id in ( SELECT DISTINCT contacts.id from contacts INNER JOIN contacts2tags ON contacts.id = contacts2tags.contactid WHERE ( tagid in ( 178 ) ) ) ) d WHERE exact = 1 OR normal = 1 ORDER BY exact desc, last_name asc LIMIT 0, 20
ОБНОВЛЕНИЕ: В соответствии с предложениями я удалил оператор LIKE для точного поиска и использовал MATCH (..) AGAINST (..) вместо LIKE в последнем случае. Хотя первое изменение немного улучшило производительность, но с помощью MATCH () AGAINST () неожиданно не изменило время выполнения. Вот обновленный запрос. PS Я пытался использовать как MATCH (все cols) AGAINST (элемент поиска), так и MATCH (single cols) AGAINST (элемент поиска) в сочетании с OR. Пожалуйста, предложите. благодаря
SELECT * FROM ( SELECT *, IF ( first_name ='Partha S' OR last_name ='Partha S' OR phone_number ='Partha S' OR mobile_number ='Partha S' OR email_address = 'Partha S' OR address ='Partha S' OR organization ='Partha S' OR other ='Partha S' OR sector ='Partha S' OR designation ='Partha S' OR concat ( first_name, ' ', last_name ) ='Partha S' OR concat ( last_name, ' ', first_name ) ='Partha S', 1, 0 ) as exact, IF ( match(first_name,last_name,phone_number,mobile_number,email_address, address,organization,other,sector,designation) against( 'Partha') OR match(first_name,last_name,phone_number,mobile_number,email_address,address,organization,other,sector,designation) against( 'S') , 1, 0 ) as normal FROM contacts WHERE id in ( SELECT DISTINCT contacts.id from contacts INNER JOIN contacts2tags ON contacts.id = contacts2tags.contactid WHERE ( tagid in ( 178 ) ) ) ) d WHERE exact = 1 OR normal = 1 ORDER BY exact desc, last_name asc LIMIT 0, 20
Одна оптимизация заключается в том, что в exact
случае вам не нужно использовать LIKE (вы должны использовать его только с шаблоном -%).
Еще одна вещь, которую вы можете сделать, чтобы сделать вещи быстрее, – это добавление INDEX к файлам, которые вы собираетесь искать.
Кроме того, только если вы используете MyISSAM в качестве механизма хранения (для этой таблицы), вы можете использовать полнотекстовый поиск, подобный этому
SELECT * FROM normal
WHERE MATCH (название, тело) ПРОТИВ ('Queried_string')
first_name LIKE '%S%' OR last_name LIKE '%S%' OR phone_number LIKE '%S%' OR mobile_number LIKE '%S%' OR email_address LIKE '%S%' OR address LIKE '%S%' OR organization LIKE '%S%' OR other LIKE '%S%' OR sector LIKE '%S%' OR designation LIKE '%S%' )
кажется, приносит очень мало значения для всего процесса.
Надеюсь это поможет.
Это не только все LIKE
, но и OR
. Даже для условий, использующих LIKE
, будут использоваться индексы. Поэтому, чтобы ускорить этот запрос, вы можете сделать один очень большой индекс для каждой таблицы, который объединяет все поля, которые вы ищете.
Но если вы действительно хотите создать поисковый запрос, вы можете захотеть использовать Sphinx или ElasticSearch вместо MySQL-запросов монстров, подобных этому.
Возможно, вам хотелось бы взглянуть на функции match()
и against()
MySQL.
Вот пример кода из их документов
mysql> CREATE TABLE articles ( -> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, -> title VARCHAR(200), -> body TEXT, -> FULLTEXT (title,body) -> ) ENGINE=MyISAM; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO articles (title,body) VALUES -> ('MySQL Tutorial','DBMS stands for DataBase ...'), -> ('How To Use MySQL Well','After you went through a ...'), -> ('Optimizing MySQL','In this tutorial we will show ...'), -> ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), -> ('MySQL vs. YourSQL','In the following database comparison ...'), -> ('MySQL Security','When configured properly, MySQL ...'); Query OK, 6 rows affected (0.00 sec) Records: 6 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM articles -> WHERE MATCH (title,body) AGAINST ('database'); +----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 1 | MySQL Tutorial | DBMS stands for DataBase ... | +----+-------------------+------------------------------------------+ 2 rows in set (0.00 sec)
ПОДРОБНЕЕ ЗДЕСЬ – http://dev.mysql.com/doc/refman/4.1/en/fulltext-natural-language.html