【问题标题】:Optimize MySQL FULL TEXT search优化 MySQL FULL TEXT 搜索
【发布时间】:2019-10-18 08:01:27
【问题描述】:

我的搜索只有一个字段,允许我在 MySQL 表的多个列中进行搜索。

这是 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

使用 PHP 预处理搜索字段以分隔每个单词的精确 SQL 查询:

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 个联系人的表中,查询时间超过 5 秒。为了更快的查询,查询或索引是否有任何可能的改进点?

【问题讨论】:

    标签: php mysql sql full-text-search full-text-indexing


    【解决方案1】:

    您是否尝试在“WHERE”子句中使用“UNION”2 组结果而不是使用“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
    

    希望这能有所帮助!

    【讨论】:

    • 是的,对于相同的请求,使用 UNION 确实快了大约 1.8 秒,但如果字段搜索为空则非常慢:12 秒。那么,如果$_POST['search']为空,我是否应该提出特殊要求?
    • 是的,我认为在执行查询之前检查输入 $_POST['search'] 是否为空有助于防止这种情况。
    【解决方案2】:

    FULLTEXT 很快; LIKE 带有前导 % 很慢; OR 很慢。

    考虑这种方法:

    1. 运行查询的MATCH 部分。
    2. 如果没有结果,则运行 LIKE 查询,但只允许使用尾随通配符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-19
      • 1970-01-01
      • 2013-03-16
      • 2011-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多