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
来减慢速度?
感谢您的投入和建设性的批评。
答案 0 :(得分:2)
您正在执行的方法CONCAT() LIKE ?
必须进行表扫描。因此,它将与表的大小成正比地变慢。
如果您需要跨多列进行全文搜索,并且希望其高效运行,则应了解MySQL's fulltext search functions。
我做了一个演示,比较了老式LIKE '%pattern%'
类型的查询和使用全文索引的搜索。这取决于您拥有多少数据,但是全文索引可以使您的查询比执行类似的查询快数百倍或数千倍。
请参阅我的演示文稿:Fulltext Search Throwdown。