【发布时间】:2016-06-26 06:24:14
【问题描述】:
我需要对此进行优化。 PHP:
$time_start = microtime(true);
$servername = "127.0.0.1";
$username = "test";
$password = "test";
$dbname = "test";
//SQL prefix
$prefix = "test_";
$mysqli = new mysqli($servername, $username, $password, $dbname);
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$gamehighestrecords = array();
function GetHighestRecord($game) {
global $gamehighestrecords, $mysqli, $prefix;
if (isset($gamehighestrecords[$game])) {
return $gamehighestrecords[$game];
} else {
$sql = $mysqli->query("SELECT rank FROM {$prefix}main_records WHERE game='{$game}' ORDER BY rank DESC LIMIT 1;");
$res = $sql->fetch_row();
$gamehighestrecords[$game] = $res[0];
return $gamehighestrecords[$game];
}
}
$sql = $mysqli->query("SELECT auth FROM test_player_data");
while ($res = $sql->fetch_array()) {
$rsql = $mysqli->query("SELECT * FROM test_records WHERE auth='{$res["auth"]}'");
$points = 0;
while ($records = $rsql->fetch_array()) {
$totalrank = GetHighestRecord($records["game"]);
$rank = $records["rank"];
if ($totalrank == 0) continue;
if ($rank == 0) continue;
$multiplier = 7500;
$points += (((1 - ($rank / $totalrank))) * $multiplier);
}
$mysqli->query("UPDATE test_player_data SET points={$points} WHERE auth='{$res["auth"]}'");
}
$time_end = microtime(true);
$execution_time = ($time_end - $time_start);
//execution time of the script
echo '<b>Total Execution Time:</b> '.$execution_time.' Seconds';
和mysql结构:
== Table structure for table test_player_data
|------
|Column|Type|Null|Default
|------
|//**id**//|int(11)|No|
|**auth**|varchar(32)|No|
|points|float|No|
|rank|int(11)|No|
.
== Table structure for table test_main_records
|------
|Column|Type|Null|Default
|------
|//**id**//|int(11)|No|
|**auth**|varchar(32)|No|
|**game**|varchar(128)|No|
|time|float|No|
|rank|int(11)|No|
test_player_data 有 ~3k 记录,test_main_records 有 ~6k 记录。 执行 php 脚本大约需要 0.7 秒(总执行时间:0.6869421005249 秒)。表格将变得更大,0.7 秒不会削减它。平均而言,每分钟将输入/更改一条新记录。然后我需要重新计算分数。我正在考虑只更新那些在那个“游戏”中有更新的记录,但以后会有成千上万的记录。
id 是主要的,auth/game 是唯一的。
我希望我在这里说得通。
另外,我知道我的代码很糟糕。这只是“概念证明”。
【问题讨论】:
-
我投票结束这个问题,因为它是代码审查。
-
可以通过在 while 循环之前启动事务并在 while 循环之后提交来加快速度。
-
并且您可以将 while 循环上方和内部的 2 个 SELECT 循环组合成 1 个单个查询,从而删除整个查询循环,例如
SELECT * FROM test_records INNER JOIN test_player_data ON test_records.auth=test_player_data.auth -
并且 GetHighestRecord 函数可以通过使用带有绑定参数的准备好的语句进行优化,这可能是一次操作 (
static $preparedStatement=false;if($preparedStatement===false){/*first-time-run make a prepared statement and bind paramters*/}),而不是每次缓存未命中时生成一个全新的查询(感谢制作缓存)
标签: php mysql sql optimization