Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 不使用rand()从mysql数据库返回随机行_Php_Mysql_Random - Fatal编程技术网

Php 不使用rand()从mysql数据库返回随机行

Php 不使用rand()从mysql数据库返回随机行,php,mysql,random,Php,Mysql,Random,我希望能够从数据库中提取15条左右的记录。我已经看到,随着数据库变得越来越大,使用WHERE id=rand可能会导致性能问题。我看到的所有解决方案都是针对选择单个随机记录。我想要倍数 有人知道一种有效的方法来处理大型数据库吗 编辑: 进一步编辑和测试: 我使用MyISAM在一个新数据库上创建了一个相当简单的表。我给了这3个字段:autokey unsigned auto number key bigdata一个大blob,还有一个中int。然后我将随机数据应用到表中,并使用Navicat运行一

我希望能够从数据库中提取15条左右的记录。我已经看到,随着数据库变得越来越大,使用WHERE id=rand可能会导致性能问题。我看到的所有解决方案都是针对选择单个随机记录。我想要倍数

有人知道一种有效的方法来处理大型数据库吗

编辑:

进一步编辑和测试:

我使用MyISAM在一个新数据库上创建了一个相当简单的表。我给了这3个字段:autokey unsigned auto number key bigdata一个大blob,还有一个中int。然后我将随机数据应用到表中,并使用Navicat运行一系列查询。结果如下:

查询1:按兰德限制从测试订单中选择*15

我尝试了select和select distinct两种方法,但没有明显的区别

以及:

我想做更多的行,这样我就可以看到Query3是如何伸缩的,但目前看来,显然胜利者是Query2

在我结束测试并声明答案之前,当我已经设置了所有这些数据和测试环境时,有人能推荐任何进一步的测试吗

更新:在中查看已接受的答案。它是纯mySQL,甚至处理均匀分布

id=rand或PHP中任何类似的问题在于,您无法确定该特定id是否仍然存在。因此,您需要使用LIMIT,这对于大量数据来说可能会变得很慢

作为替代方案,您可以尝试在PHP中使用循环

循环的作用是

使用rand创建一个随机整数,范围介于0和数据库中的记录数之间

查询数据库是否存在具有该ID的记录

如果存在,请将该数字添加到数组中

如果没有,请返回步骤1

当随机数数组包含所需数量的元素时,结束循环

这种方法可能会在一个碎片化的表中产生大量查询,但执行起来应该非常快。在某些情况下,它可能比极限兰德快


如@Luther所述,LIMIT方法无疑是最简单的代码方式。

您可以使用所有结果进行查询,或者使用有限的结果进行查询,然后使用mysqli\u fetch\u all,后跟:

shuffle($a);
$a = array_slice($a, 0, 15);
尝试:

另一种可能更有效的方法是针对一组随机值进行连接。如果表中有一些连续的整数键,这应该可以工作。以下是我在postgres中的做法我的MySQL有点生锈了

select * from table join 
   (select (random()*maxid)::integer as val from generate_series(1,15)) as rnd
   on rand.val=table.id;
其中,maxid是表中的最高id。若id有一个索引,那个么这意味着只有15个索引查找,所以它非常快

更新:

看起来MySQL中没有生成_系列这样的东西。是我的错。实际上,我们并不需要它:

select * 
from 
 table 
join 
 -- this just returns 15 random numbers. 
 -- I need `table` here only to produce rows for rand()
 (select round(rand()*(select max(id) from table)) as val from table limit 15) as rnd
on 
 rnd.val=table.id;

另外,如果我不希望返回重复项,我可以在随机生成器表达式中使用select distinct[…]。

用于大型数据集

select * from table order by rand() limit 15
这可能会耗费大量的时间和内存

如果您的数据记录碰巧被编号,您可以在编号栏上放置和索引,并执行以下操作:

select * from table where no >= rand() limit 15
或者最好在应用程序中生成随机数,然后

select * from table where no >= $rand and no <= $rand+15

如果您的数据不经常更改,那么可能值得添加这样的列编号,以提高选择的效率。

假设MySQL支持嵌套查询,并且主键上的操作速度很快,我会尝试以下方法

select * from table where id in (select id from table order by rand() limit 15)

这些可能会有帮助:,这很难节省内存-他询问的是更大的数据量。他确实说过他只想要15行,这取决于查询带来的回退量,但实际上不是15行随机数据。它是一个随机行,然后是结果中的下14行,如果$rand恰好位于表中最后15条记录的范围内,它也将不起作用。
select * from table order by rand() limit 15
select * from table where no >= rand() limit 15
select * from table where no >= $rand and no <= $rand+15
select * from table where id in (select id from table order by rand() limit 15)