2011-02-18 73 views
1

我開發了一個相當簡單的腳本來搜索數據庫,然後根據搜索條件對搜索結果進行排序,所以試圖首先得到最相關的結果。PHP腳本優化 - MySql搜索和排序

現在這個運行良好我的本地機器上,我把在排序前跑好吧,我已經聘請了在Web服務器上,但一旦進行排序的搜索時間去在Web服務器上有了很大的提高。

我在下面發佈的內容我已經儘可能多地進行了優化,因此我正在尋找更好的排序算法中的一些幫助,甚至可能是查詢數據庫的更好方法以幫助加快排序時間!

現在需要允許或例如貓或汽車的3個字母搜索更多關於我與我的工作的一些信息,我無法改變自然搜索詞時長限制MySQL服務器,所以我不能使用mysql的自然語言搜索,因此爲什麼我正在做我目前的查詢。

而且平均搜索可以隨時隨地輕鬆100-15000之間的結果與數據庫保持圍繞20000項

任何幫助將返回不勝感激

<?php 

require_once 'config.php'; 

$bRingtone = true; 

$aSearchStrings = $_POST["searchStrings"]; 

$cConnection = new mysqli($dbhost, $dbuser, $dbpass, $dbname); 

if (mysqli_connect_errno()) 
{ 
    exit(); 
} 

$sTables = array("natural", "artificial", "musical", "created"); 

$aQueries = array(); 

foreach ($sTables as $sTable) 
{ 
    $sQuery = "SELECT filename, downloadPath, description, imageFilePath, keywords FROM `$sTable` WHERE"; 

    $sParamTypes = ""; 
    $aParams = array(); 

    $iCount = 0; 

    foreach ($aSearchStrings as $sString) 
    { 
      $sParamTypes .= "ss"; 

      $aParams[] = "%,$sString%"; 
      $aParams[] = "$sString%"; 

      $sQuery .= $iCount++ == 0 ? " (keywords LIKE ? OR keywords LIKE ?)" : " AND (keywords LIKE ? OR keywords LIKE ?)"; 
    } 

    array_unshift($aParams, $sParamTypes); 

    $aQueries[$sQuery] = $aParams; 
} 

$aResults = array(); 

foreach ($aQueries as $sQuery => $aParams) 
{ 
    if ($cStmt = $cConnection->prepare($sQuery)) 
    { 
      $aQueryResults = array(); 

      call_user_func_array(array($cStmt, 'bind_param'), $aParams); 

      $cStmt->execute(); 

      $cStmt->bind_result($sFileName, $sDownloadPath, $sDescription, $sImageFilePath, $sKeywords); 

      while($cStmt->fetch()) 
      { 
        if ($bRingtone) 
        { 
          $sFileName = $_SERVER['DOCUMENT_ROOT'] . "/m4r/" . str_replace(".WAV", ".M4R", $sFileName); 
          if (file_exists($sFileName)) 
          { 
            $sDownloadPath = str_replace("Sounds", "m4r", str_replace(".WAV", ".M4R", $sDownloadPath)); 
            $aResults[$sDownloadPath] = array($sDownloadPath, $sDescription, $sImageFilePath, $sKeywords, $aSearchStrings); 
          } 
        } 
      } 

      $aResults = array_merge($aResults, $aQueryResults); 

     $cStmt->close(); 
    } 
} 

$cConnection->close(); 

$aResults = array_values($aResults); 

function in_arrayi($needle, $haystack) { 
    return in_array(strtolower($needle), array_map('strtolower', $haystack)); 
} 

function keywordSort($a, $b) 
{ 
    if ($a[0] === $b[0]) return 0; 

    $aKeywords = explode(",", $a[3]); 
    $bKeywords = explode(",", $b[3]); 

    foreach ($a[4] as $sSearchString) 
    { 
     $aFound = in_arrayi($sSearchString, $aKeywords); 
     $bFound = in_arrayi($sSearchString, $bKeywords); 

     if ($aFound && !$bFound) 
     { 
      return -1; 
     } 
     else if ($bFound && !$aFound) 
     { 
      return 1; 
     } 
    } 

    return 0; 
} 

usort($aResults, "keywordSort"); 

foreach ($aResults as &$aResult) 
{ 
    unset($aResult[3]); 
    unset($aResult[4]); 
} 

echo json_encode($aResults); 

?> 
+0

*」現在在我的本地機器上運行良好,並且在我已經僱傭的Web服務器上進行分類之前,運行良好,但是一旦排序進入搜索時間,Web服務器的搜索時間就大大增加了。「* 這可能基於您的本地服務器的內存/分配(memory_limit)與您的遠程服務器。 – TNC 2011-02-18 16:14:00

回答

2

排序,而不必拆分大量數據現場代碼端會很慢。我不會優化,而是會認真地推薦另一種方法,比如全文索引。一旦它工作,它真的很整齊。

如果全文真的是不是一種選擇,我建議拆分關鍵字斷成一個單獨的表。這樣,您可以在分組後根據計數進行排序。例如...

SELECT d.*, COUNT(k.id) AS keywordcount 
FROM data d 
    INNER JOIN keywords k ON (d.id = k.dataid) 
WHERE k.value IN ('keyword1', 'keyword2', 'keyword3') 
GROUP BY d.id 
ORDER BY keywordcount 

在另一PSish型筆記,你也許可以通過UNIONing的選擇,其次是訂貨,而不是獨立運行他們都加快的事情。 「