Я не отличный PHP-кодер (я из C++). Я использую php только для ввода базы данных.PhP, MySql - Код оптимизации
У меня есть база данных со следующим:
UserId (an unique int)
AsyncPointsAverage (float)
AsyncPointsAverageRank (a position based on the value immediately above)
AsyncPointsRecentAverage (float an average for the last 5 tests only)
AsyncPointsRecentAverageRank (a position based on the value immediately above)
Есть около 1000-1500 записей в этой таблице. Каждое утро и во второй половине дня 5 человек проходят тест, который влияет на их среднее среднее и последнее среднее значение. (Это обновляется в другом месте, но не показано здесь.) После этого рассчитано для этих 5 человек, тогда рейтинг всех 1000-1500 будет выполнен, поэтому я написал код ниже. Это оптимально?
То, что меня больше всего волнует, я делаю MySql UPDATE около 1000 раз. Это здорово? Должен ли я делать это по-другому? (Также вы можете оптимизировать любой другой код в функции. Как я уже говорил, я из C++ фона, так что на самом деле не знаю нюансы PHP.)
// Sorts by array entry 1
function ReRankCompareAverage($a, $b)
{
if($a[1] == $b[1]) return 0;
else return ($a[1] > $b[1] ? 1 : -1);
}
// Sorts by array entry 2
function ReRankCompareAverageRecent($a, $b)
{
if($a[2] == $b[2]) return 0;
else return ($a[2] > $b[2] ? 1 : -1);
}
function ReRank($db)
{
$i = 0, $j = 0;
$usersARR = null;
$stmt = $db->prepare("SELECT UserId, AsyncPointsAverage, AsyncPointsRecentAverage FROM studenttable");
$stmt->execute();
if($stmt && isset($stmt) && $stmt->rowCount() > 0)
{
$i = 0;
while(($row = $stmt->fetch(PDO::FETCH_ASSOC)))
{
$usersARR[$i][0] = intval($row['UserId']);
$usersARR[$i][1] = floatval($row['AsyncPointsAverage']);
$usersARR[$i][2] = floatval($row['AsyncPointsRecentAverage']);
$i++;
}
}
$stmt->closeCursor(); // mysql_free_result equivalent
// The first pass of $j == 3 does the ranking by Average, filling position $usersARR[][3] with that rank
// The second pass of $j == 4 does the ranking by AverageRecent, filling position $usersARR[][4] with that rank
for($j = 3, $j <= 4; $j++)
{
$iCompare = $j == 3 ? 1 : 2;
usort($usersARR, $j == 3 ? "ReRankCompareAverage" : "ReRankCompareAverageLast");
$count = count($usersARR);
if($count > 0)
{
// Start it off, with the person with the highest average is rank 1
$usersARR[$count - 1][$j] = 1; // Position $j is filled with the rank
// Now loop starting from the second one down
for($i = $count - 2, $rank = 1; $i >= 0; $i--)
{
// Only change the rank if the next one down is strictly lower than the one above, otherwise will share the same rank
if($usersARR[$i][$iCompare] < $usersARR[$i+1][$iCompare]) $rank = $count - $i; // Otherwise keep the same rank, because they are equal
$usersARR[$count - 1][$j] = $rank;
}
}
}
// Now $usersARR is filled with the correct rankings, and they are asscoiated with $UserId
// Now we must put all of these rankings into the database
$count = count($usersARR);
for($i = 0; $i < $count; $i++)
{
$stmt = $db->prepare("UPDATE studenttable SET AsyncPointsAverageRank=:AsyncPointsAverageRank, AsyncPointsRecentAverageRank=:AsyncPointsRecentAverageRank "
. "WHERE UserId=:UserId");
$stmt->execute(array(':AsyncPointsAverageRank' => $usersARR[$i][3],
':AsyncPointsRecentAverageRank' => $usersARR[$i][4],
':UserId' => $usersARR[$i][0]));
}
}
Вы можете использовать транзакцию и делать все обновления. Я не уверен, поддерживает ли MyISAM транзакцию, но InnoDb делает. – frz3993
Ваш код безопасен для инъекций, а тысяча небольших запросов на обновление не является проблемой для любого современного сервера базы данных. Я бы сказал, что все в порядке. Если вы хотите продолжить оптимизацию, вы ошибаетесь на сайте StackExchange. :) –
Не заглядывал в детали вашей проблемы, так как, как вы делаете, это кажется прекрасным, но, просто для «цели обсуждения», если вы хотите избежать тысячи обновлений в своем db, вам стоит подумать о другом «рейтинге» ", как столбец в вашей таблице, который ссылается на« предыдущий »или« следующий элемент ». Таким образом, ваше ранжирующее обновление повлияет только на «реклассифицированные» предметы и соседей ... – Julo0sS