我已经在php页面上运行了1000次foreach循环。foreach循环中的代码如下所示:
$first = mysql_query("SELECT givenname FROM first_names order by rand() LIMIT 1");
$first_n = mysql_fetch_array($first);
$first_name = $first_n['givenname'];
$last = mysql_query("SELECT surname FROM last_name order by rand() LIMIT 1");
$last_n = mysql_fetch_array($last);
$last_name = $last_n['surname'];
$first_lastname = $first_name . " " . $last_name;
$add = mysql_query("SELECT streetaddress FROM user_addresss order by rand() LIMIT 1");
$addr = mysql_fetch_array($add);
$address = $addr['streetaddress'];
$unlisted = "unlisted";
$available = "available";
$arr = array(
$first_lastname,
$address,
$unlisted,
$available
);然后,我使用array_rand函数在每次循环运行时获得随机化值:
<td><?php echo $arr[array_rand($arr)] ?></td>所以加载php页面需要很长的时间。有没有办法可以优化这段代码。因为每次循环运行时我都需要一个唯一的值
发布于 2013-05-15 01:12:52
问题不在于PHP foreach循环。如果你用RAND()命令你的MySQL表,你就犯了一个严重错误的。让我向你解释一下当你这样做的时候会发生什么。
每次您发出MySQL请求时,MySQL都会尝试将您的搜索参数(WHERE、ORDER BY)映射到索引,以减少数据读取。然后,它会将相关信息加载到内存中进行处理。如果信息太大,它将默认将其写入磁盘并从磁盘读取以执行比较。您希望不惜一切代价避免磁盘读取,因为它们低效、缓慢、重复,并且在特定情况下有时会完全错误。
当MySQL找到可能使用的索引时,它将改为加载索引表。索引表是存储位置和索引值之间的哈希表。例如,主键的索引表如下所示:
id location
1 0 bytes in
2 17 bytes in
3 34 bytes in这是非常高效的,因为即使是非常大的索引表也可以放入极少量的内存中。
为什么我要讨论索引?,因为通过使用RAND(),您可以阻止MySQL使用它们的。ORDER BY RAND()强制MySQL为每行创建一个新的随机值。这需要MySQL复制临时表中的所有表数据,并添加一个具有RAND()值的新字段。此表太大,无法存储在内存中,因此将存储到磁盘。
当您告诉MySQL按RAND()排序并创建表时,MySQL将按对比较每一行(MySQL排序使用快速排序)。由于行太大,因此您需要在此操作中查看相当多的磁盘读取。当它完成时,它会返回,您将以巨大的成本获得数据-at。
有很多方法可以防止这种大规模的开销混乱。其中之一是从RAND()中选择ID到最大索引并限制为1。这不需要创建额外的字段。类似的堆栈问题还有很多。
发布于 2013-05-15 01:21:21
前面已经解释了为什么应该避免ORDER BY RAND(),所以我简单地提供了一种使用一些更快的查询来做到这一点的方法。
首先,根据您的表大小获取一个随机数:
SELECT FLOOR(RAND()*COUNT(*)) FROM first_names其次,在限制中使用随机数
SELECT * FROM first_names $pos,1不幸的是,我认为没有任何方法可以将这两个查询合并为一个查询。
您还可以执行一次SELECT COUNT(*) FROM first_names,存储数字,并在PHP中生成任意次数的随机$pos。
发布于 2013-05-15 01:23:56
如果您的主机支持mysqli或pdo,您应该切换到mysqli或pdo,但这样的东西应该可以工作。但是,如果两个表中都没有足够的记录,则必须确定要执行的操作(array_pad或包装索引并重新启动)
function getRandomNames($qty){
$qty = (int)$qty;
$fnames = array();
$lnames = array();
$address = array();
$sel =mysql_query("SELECT givenname FROM first_names order by rand() LIMIT ".$qty);
while ($rec = mysql_fetch_array($sel)){$fnames[] = $rec[0]; }
$sel =mysql_query("SELECT surname FROM last_name order by rand() LIMIT ".$qty);
while ($rec = mysql_fetch_array($sel)){ $lnames[] = $rec[0]; }
$sel =mysql_query("SELECT streetaddress FROM user_addresss order by rand() LIMIT ".$qty);
while ($rec = mysql_fetch_array($sel)){ $address[] = $rec[0]; }
// lets stitch the results together
$results = array();
for($x = 0; $x < $qty; $x++){
$results[] = array("given_name"=>$fnames[$x], "surname"=>$lnames[$x], "streetaddress"=>$address[$x]);
}
return $results;
}希望这能有所帮助
更新
根据Sébastien Renauld的回答,更完整的解决方案可能是构造查询,如下所示
"SELECT givenname from first_names where id in (select id from first_names order by rand() limit ".$qty.")";https://stackoverflow.com/questions/16548900
复制相似问题