I have a search with only one field that allows me to search in several columns of a MySQL table.
This is the SQL query:
SELECT td__user.* FROM td__user LEFT JOIN td__user_oauth ON td__user.id = td__user_oauth.user_id WHERE ( td__user.id LIKE "contact@mywebsite.com" OR (MATCH (email, firstname, lastname) AGAINST (+"contact@mywebsite.com" IN BOOLEAN MODE)) ) ORDER BY date_accountcreated DESC LIMIT 20 OFFSET 0
The exact SQL query with PHP pre-processing of the search field to separate each word:
if($_POST['search'] == '') { $searchId = '%'; } else { $searchId = $_POST['search']; } $searchMatch = ''; foreach($arrayWords as $word) { $searchMatch .= '+"'.$word.'" '; } $sqlSearch = $dataBase->prepare('SELECT td__user.*, td__user_oauth.facebook_id, td__user_oauth.google_id FROM td__user LEFT JOIN td__user_oauth ON td__user.id = td__user_oauth.user_id WHERE ( td__user.id LIKE :id OR (MATCH (email, firstname, lastname) AGAINST (:match IN BOOLEAN MODE)) ) ORDER BY date_accountcreated DESC LIMIT 20 OFFSET 0); $sqlSearch->execute(['id' => $searchId, 'match' => $searchMatch]); $searchResult = $sqlSearch->fetchAll(); $sqlSearch->closeCursor();
The SQL query works well, when I put an ID in the search field or a first name or a last name, or an email even not complete I have results. I can also put a first name and a last name in my search field and I will only result in people with this name.
On the other hand, in a table containing 500,000 contacts, the query takes more than 5 seconds. Are there any possible points for improvement in the query or in the indexes to be done in order to have a faster query?
Advertisement
Answer
Did you try to use “UNION” 2 sets of results instead of using the “OR” operator in the “WHERE” clause? Because I’m just afraid of the index can not be used with the “OR” operator.
The query will be something like this:
SELECT td__user.*, td__user_oauth.facebook_id, td__user_oauth.google_id FROM td__user LEFT JOIN td__user_oauth ON td__user.id = td__user_oauth.user_id WHERE td__user.id LIKE :id UNION SELECT td__user.*, td__user_oauth.facebook_id, td__user_oauth.google_id FROM td__user LEFT JOIN td__user_oauth ON td__user.id = td__user_oauth.user_id WHERE MATCH (email, firstname, lastname) AGAINST (:match IN BOOLEAN MODE)) ORDER BY date_accountcreated DESC LIMIT 20 OFFSET 0
Hope this can help!