优化MySQL或PHP的搜索功能

时间:2017-01-18 21:21:13

标签: php mysql algorithm optimization

运行一些测试后,我意识到如果查询的某些单词很短(2~3个字母),我的搜索方法效果不佳。

我进行搜索的方式是对访问者输入的字符串中的每个单词进行MySQL查询,然后从每个单词中过滤结果,看看每个单词是否都有该结果。一旦为所有单词返回一个结果,它就会匹配并向结果显示结果。

但我想知道这是否是一种有效的方法。在保持相同功能的同时还有更好的方法吗?

目前,我已经采用了.7Sec进行MySQL查询的代码。剩下的东西都在.1Sec之下。 通常我不会太在意我的搜索.7Sec,但我喜欢创建一个" LiveSearch"而且加载速度要快得多。

这是我的代码

    public static function Search($Query){
        $Querys = explode(' ',$Query);
        foreach($Querys as $Query)
        {
            $MatchingRow = \Database\dbCon::$dbCon -> prepare("
                SELECT
                    `Id`
                FROM
                    `product_products` as pp
                WHERE
                    CONCAT(
                        `Id`,
                        ' ',
                        (SELECT `Name` FROM `product_brands` WHERE `Id` = pp.BrandId),
                        ' ',
                        `ModelNumber`,
                        ' ',
                        `Title`,
                        IF(`isFreeShipping` = 1 OR `isFreeShippingOnOrder` = 1, ' FreeShipping', '')
                    )
                LIKE :Title;
                ");
            $MatchingRow -> bindValue(':Title','%'.$Query.'%');
            try{
                $MatchingRow -> execute();
                foreach($MatchingRow -> fetchAll(\PDO::FETCH_ASSOC) as $QueryInfo)
                    $Matchings[$Query][$QueryInfo['Id']] = $QueryInfo['Id'];
            }catch(\PDOException $e){
                echo 'Error MySQL: '.$e->getMessage();
            }
        }
        $TmpMatch = $Matchings;
        $Matches = array_shift(array_values($TmpMatch));
        foreach($TmpMatch as $Query)
        {
            $Matches = array_intersect($Matches,$Query);
        }
        foreach($Matches as $Match){
            $Products[] = new Product($Match);
        }
        return $Products;
    }

1 个答案:

答案 0 :(得分:0)

正如其他人已经建议的那样,fulltext search是你的朋友。

逻辑应该或多或少地像这样。

  • 将文本列添加到" product_products"表格,比方说," FtSearch"
  • 编写一个只运行一次的小脚本,在其中为每个现有产品编写必须搜索的文本到" FtSearch"柱。当然,这是您在查询中撰写的文本(id +品牌名称+标题等等,包括FreeShipping部分)。您可以使用单个SQL语句执行此操作,但我手头没有mysql并且无法为您提供代码...您可以自己找到它。
  • 在" FtSearch"上创建全文索引column(在填充FtSearch列之后执行此可以节省一点执行时间。)
  • 现在,您必须添加必要的代码,以确保每次插入/更新搜索字符串中涉及的任何字段时,您也会插入/更新搜索字符串。请注意这里,因为这不仅包括" Title"," ModelNumber"和#34; FreeShipping" " product_product",以及"名称" " product_brand"。这意味着如果更新product_brand的名称,则必须重新生成具有该品牌的所有产品的所有搜索字符串。这可能有点慢,这取决于该品牌的产品数量。但是我认为品牌改名不会经常发生,如果确实如此,它肯定会发生在某种管理界面上,这种情况通常是可以接受的。
  • 此时,您可以使用MATCH构造查询表格,这可以通过使用您当前的方法获得更快的速度。