优化 MySQL 全文搜索
Optimize MySQL FULL TEXT search
我的搜索只有一个字段,允许我在 MySQL table.
的多个列中进行搜索
这是 SQL 查询:
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
精确的 SQL 查询,PHP 对搜索字段进行预处理以分隔每个单词:
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();
这些是我的索引:
SQL 查询效果很好,当我在搜索字段中输入 ID 或名字或姓氏,或者电子邮件甚至不完整时,我都有结果。我还可以在我的搜索字段中输入名字和姓氏,我只会搜索到具有此名字的人。
另一方面,在包含 500,000 个联系人的 table 中,查询需要超过 5 秒。为了加快查询速度,查询或索引中是否有任何可能的改进点?
您是否尝试使用 "UNION" 2 组结果而不是在 "WHERE" 子句中使用 "OR" 运算符?因为我就是怕索引不能和"OR"运算符一起使用。
查询将是这样的:
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
希望对您有所帮助!
FULLTEXT
快; LIKE
前导 %
很慢; OR
很慢。
考虑这种方法:
- 运行 查询的
MATCH
部分。
- 如果没有结果,则 运行
LIKE
查询但只允许尾随通配符。
我的搜索只有一个字段,允许我在 MySQL table.
的多个列中进行搜索这是 SQL 查询:
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
精确的 SQL 查询,PHP 对搜索字段进行预处理以分隔每个单词:
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();
这些是我的索引:
SQL 查询效果很好,当我在搜索字段中输入 ID 或名字或姓氏,或者电子邮件甚至不完整时,我都有结果。我还可以在我的搜索字段中输入名字和姓氏,我只会搜索到具有此名字的人。
另一方面,在包含 500,000 个联系人的 table 中,查询需要超过 5 秒。为了加快查询速度,查询或索引中是否有任何可能的改进点?
您是否尝试使用 "UNION" 2 组结果而不是在 "WHERE" 子句中使用 "OR" 运算符?因为我就是怕索引不能和"OR"运算符一起使用。
查询将是这样的:
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
希望对您有所帮助!
FULLTEXT
快; LIKE
前导 %
很慢; OR
很慢。
考虑这种方法:
- 运行 查询的
MATCH
部分。 - 如果没有结果,则 运行
LIKE
查询但只允许尾随通配符。