Оптимизация сценариев PHP - поиск и сортировка MySql - PullRequest
1 голос
/ 18 февраля 2011

Я разработал довольно простой скрипт для поиска в базе данных, а затем отсортировал результаты по используемым поисковым терминам, поэтому сначала пытаюсь найти наиболее релевантные.

Теперь это работало нормально на моем локальном компьютере и раньше.Я установил, что сортировка прошла нормально на веб-сервере, который я нанял, но как только сортировка прошла, время поиска на веб-сервере значительно увеличилось.

То, что я публикую ниже, я оптимизировал настолько, насколько я знаю, какПоэтому мне нужна помощь в улучшенном алгоритме сортировки и, возможно, даже в лучшем способе запроса к базе данных, что поможет ускорить время сортировки!

Теперь нужна некоторая информация о том, с чем я работаюразрешить поиск 3 или более букв, например, cat или car, и я не смог изменить ограничение естественной длины слова поиска для сервера 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);

?>

1 Ответ

2 голосов
/ 18 февраля 2011

Сортировка больших объемов данных при разделении стороны кода будет медленной.Вместо того, чтобы оптимизировать, я бы серьезно рекомендовал другой способ сделать это, например, полнотекстовое индексирование.Это действительно довольно аккуратно, как только он работает.

Если полнотекстовый действительно не вариант, я бы рекомендовал разбить ключевые слова в отдельной таблице.Таким образом, вы можете сортировать по количеству после группировки.Например ...

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 вы, вероятно, можете ускорить процесс, объединив выборки с последующим упорядочением, вместо того, чтобы запускать их все независимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...