优化所有相关的字段搜索方法

时间:2019-03-26 21:42:48

标签: php mysql

Id想看看是否有更好的方法可以优化以下搜索方法。

我完全意识到我当前正在从mysql查询返回一些未使用的字段。我计划实际使用它们。因此,一旦使用Customer constructor

,我就不会“重复获取”数据
        static function ByAny($SearchString){
            $Get = dbCon::$dbCon -> prepare("
SELECT cC.Id as cC_Id,cC.FirstName as cC_FirstName,cC.LastName as cC_LastName,cC.EmailAddress as cC_EmailAddress,cC.Note as cC_Note,
    cF.Id as cF_Id,cF.Name as cF_Name, cF.Notes as cF_Note,
    cA.Address as cA_Address, cA.City as cA_City, cA.PostalCode as cA_PostalCode,cA.Province as cA_Province, cA.Country as cA_Country,cA.Description as cA_Description,
    cFA.Address as cFA_Address, cFA.City as cFA_City, cFA.PostalCode as cFA_PostalCode,cFA.Province as cFA_Province, cFA.Country as cFA_Country,cFA.Description as cFA_Description
FROM
    `customer_customers` as cC
        LEFT JOIN customer_farms as cF ON (cC.FarmId = cF.Id)
        LEFT JOIN addresses as cA ON (cC.AddressId = cA.Id)
        LEFT JOIN addresses as cFA ON (cF.AddressId = cFA.Id)
WHERE
    CONCAT_WS(
        cC.FirstName,' ',cC.LastName,' ',cC.EmailAddress,' ',cC.Note,' ',
        cF.Name,' ',cF.Notes,' ',
        cA.Address,' ',cA.City,' ',cA.PostalCode,' ',cA.Province,' ',cA.Country,' ',cA.Description,
        cFA.Address,' ',cFA.City,' ',cFA.PostalCode,' ',cFA.Province,' ',cFA.Country,' ',cFA.Description
    ) LIKE :Like;
            ");

            $CustomerObjAr = array();

            $SearchResult = null;
            foreach(explode(' ',$SearchString) as $Q){ //Explode string by spaces, then search all words
                $Get -> bindValue(':Like','%'.$Q.'%');
                try{
                    $Get -> execute();

                    if(is_null($SearchResult)){ // Is first time search run, All result should be kept.
                        $SearchResult = array();
                        foreach($Get->fetchAll(\PDO::FETCH_ASSOC) as $cData){
                            $SearchResult[] = $cData['cC_Id'];
                        }
                    }else{ // We already have result, lets compare them with new result, and keep only matching ( Closing narrowing search result )
                        $cSearchResult = array();
                        foreach($Get->fetchAll(\PDO::FETCH_ASSOC) as $cData){
                            $cSearchResult[] = $cData['cC_Id'];
                        }
                        $SearchResult = array_intersect($SearchResult,$cSearchResult);
                    }
                    if(is_array($SearchResult) && count($SearchResult) == 0) //No more result, lets terminate this now.
                        return $SearchResult;

                }catch (\PDOException $e){
                    die("Error while searching customers by any field: ".$e->getMessage());
                }
            }
            foreach($SearchResult as $cId){
                $CustomerObjAr[] = new Customer($cId);
            }
            return $CustomerObjAr;
        }

我当时正在考虑为已知的匹配结果添加一个IN (1,2,3)子句,但是我不确定提供列表的实际好处,它可以在mysql方面加快速度吗?还是会先选择它们然后运行CONCAT() LIKE来减慢速度?

感谢您的投入和建设性的批评。

1 个答案:

答案 0 :(得分:2)

您正在执行的方法CONCAT() LIKE ?必须进行表扫描。因此,它将与表的大小成正比地变慢。

如果您需要跨多列进行全文搜索,并且希望其高效运行,则应了解MySQL's fulltext search functions

我做了一个演示,比较了老式LIKE '%pattern%'类型的查询和使用全文索引的搜索。这取决于您拥有多少数据,但是全文索引可以使您的查询比执行类似的查询快数百倍或数千倍。

请参阅我的演示文稿:Fulltext Search Throwdown