我在php + mysql中有项目(超过2 000 000行)。请查看此PHP代码。
<?php
for($i=0;$i<20;$i++)
{
$start = rand(1,19980);
$select_images_url_q = "SELECT * FROM photo_gen WHERE folder='$folder' LIMIT $start,2 ";
$result_select = (mysql_query($select_images_url_q));
while($row = mysql_fetch_array($result_select))
{
echo '<li class="col-lg-2 col-md-3 col-sm-3 col-xs-4" style="height:150px">
<img class="img-responsive" src="http://static.gif.plus/'.$folder.'/'.$row['code'].'_s.gif">
</li>';
}
}
?>
这段代码在$start = rand(1,19980);
位置工作得非常慢,请帮助我如何使用mysql随机函数进行选择请求,谢谢
答案 0 :(得分:2)
根据您的代码使用$folder
执行的操作,您可能容易受到SQL injection的攻击。</ p>
为了更好的安全性,请考虑转移到PDO或MySQLi和using prepared statements。我编写了一个名为EasyDB的库,以便开发人员更容易采用更好的安全实践。
从数据库中选择N个不同随机元素的快速,合理和有效的方法如下:
WHERE folder = ?
)。使用EasyDB的示例如下:
// Connect to the database here:
$db = \ParagonIE\EasyDB\Factory::create(
'mysql;host=localhost;dbname=something',
'username',
'putastrongpasswordhere'
);
// Maintain an array of previous record IDs in $exclude
$exclude = array();
$count = $db->single('SELECT count(id) FROM photo_gen WHERE folder = ?', $folder);
// Select _up to_ 40 values. If we have less than 40 in the folder, stop
// when we've run out of photos to load:
$max = $count < 40 ? $count : 40;
// The loop:
for ($i = 0; $i < $max; ++$i) {
// The maximum value will decrease each iteration, which makes
// sense given that we are excluding one more result each time
$r = mt_rand(0, ($count - $i - 1));
// Dynamic query
$qs = "SELECT * FROM photo_gen WHERE folder = ?";
// We add AND id NOT IN (2,6,7,19, ...) to prevent duplicates:
if ($i > 0) {
$qs .= " AND id NOT IN (" . implode(', ', $exclude) . ")";
}
$qs .= "ORDER BY id ASC LIMIT ".$r.", 1";
$row = $db->row($qs, $folder);
/**
* Now you can operate on $row here. Feel free to copy the
* contents of your while($row=...) loop in place of this comment.
*/
// Prevent duplicates
$exclude []= (int) $row['id'];
}
Gordon's answer建议使用ORDER BY RAND()
,in general is a bad idea并且可以使您的查询速度非常慢。此外,尽管他说您不必担心少于40行(可能是因为涉及的概率),但将在边缘情况下失败。
关于mt_rand()
的快速说明:这是一个有偏见且可预测的随机数生成器,只有40亿种可能的种子。如果你想要更好的结果,look into random_int()
(仅限PHP 7,但我正在为PHP 5项目开发兼容层。有关详细信息,请参阅链接的答案。)
答案 1 :(得分:1)
实际上,即使该表有200多万行,我也猜测给定的文件夹少了很多。因此,对于photo_gen(folder)
:
SELECT *
FROM photo_gen
WHERE folder = '$folder'
ORDER BY rand()
LIMIT 40;
如果一个文件夹仍然可以包含数十或数十万个示例,我建议稍微改变一下:
SELECT pg.**
FROM photo_gen pg cross join
(select count(*) cnt from photo_gen where folder = $folder) as cnt
WHERE folder = '$folder' and
rand() < 500 / cnt
ORDER BY rand()
LIMIT 40;
WHERE
表达式应该大约有500行(受样本变异的影响)。有一个非常高的信心,至少有40个(你不必担心它)。最后的排序应该很快。
肯定有其他方法,但它们因where
子句而变得复杂。索引可能是提高性能所需的关键因素。
答案 2 :(得分:0)
最好先将你的SQL查询(在PHP中作为一个字符串)编写一次,然后再执行一次。
或者您可以使用这种方式选择适合您情况的值:Select n random rows from SQL Server table