2009-11-05 98 views
1

我读过,在大型数据库上使用ORDER BY RAND()运行SQL查询并不是一个好主意。随机记录Mysql PHP

因此,这是我在分解代码时的一个镜头。代码需要从数据库中选择10个随机ID,然后再进行一次选择以抓取随机行。

$sql = "SELECT id FROM table WHERE image != '' 
     ORDER BY id DESC LIMIT 50;"; 

$result = mysql_query($sql); 


while($row = mysql_fetch_array($result)) 
{ 
    foreach($row as $key => $value) 
    { 
     $array[] = $value; 
    } 
} 
$rand_keys = array_rand($array, 10); 

foreach($rand_keys as $value) 
{ 

    $rand_arr[] = $array[$value]; 

} 
$rand_list = implode("," , $rand_arr); 

$sql = "SELECT image FROM table 
     WHERE image != '' 
     AND id IN ($rand_list)"; 
$result = mysql_query($sql); 

任何建议加快或简化?

回答

2

四件事情:

  1. 你干吗打50 id■如果你只需要12? (你正在从最近的50个选择12个ID - 这是有道理的,尽管在一般意义上这个词不是特别随意的 - 那是故意选择你想要从中挑选行的子集?)。

  2. 你是否已经对SQL语句ORDER BY RAND()进行了概要分析,看看它是否对你来说很慢?你的数据集有多大?

  3. 在最后一个查询中不需要WHERE image != '',因为您已经选取了id s,其中image != ''

  4. 你为什么要做array_rand($array, 10) - 你说你想要12个值?

  5. 可以简化挑选出随机值是这样的:

$rand_arr = array_rand(array_flip($array), 12);

+0

我真的会避免rand()作为一般习惯。我已经看到了这个只有几十万行的MyISAM表。 – 2009-11-05 09:31:01

+0

来吧,现在多米尼克。 #3和#4是明显的拼写错误/被忽略的想法。我的错。 #5非常有帮助。 #2在我心中。我在共享服务器上运行这段代码,它使我的网站停下来(实际上与ORDER BY rand()效果相同)。这使我重新思考完全随机的行,即。提供随机图像。 – rrrfusco 2009-11-17 01:21:10

0

我会用点1同意以上2 - 如果你能内进行的随机数据的选择您的应用程序与数据所在的同一级别相同,您需要编写的程序才能完成同样的任务。

0

有没有特别好的方法来优雅地做到这一点。

但是你可以从很多方面入手。如果你的数据集大小合适(“rand()顺序太大”,但不是太大),具有顺序的id值,并且一般不会删除太多,所以你总是可以这样做:

SELECT MIN(id) as min, MAX(id) as max FROM table 

在“min”和“max”(含)之间生成N个随机整数。我们把它称为50.如果你从不删除表中的任何东西,N可能是12.如果你删除,做一些餐巾算术,并找出一个好数字。你可能会偏高。

SELECT * FROM table WHERE id IN (<your set of integers>) AND image_id = '' LIMIT 12; 

检查并确保你得到至少12条结果。如果没有,基本上重复和结合。

对于大型集合,此方法应该比ORDER BY RAND()更好,尤其是如果您的ID序列不是非常稀疏。

+0

我喜欢这种方法,但它只适用于auto_increment单调的单主设置:auto_increment_increment,auto_increment_offset设置可以将这些id分散出去。 – 2009-11-05 09:28:56

+0

好点。这只有在你开始处理多个主人时才会起作用。 – timdev 2009-11-05 09:40:54

0

我会专注于Dominic的第5点,它是一种影响相当小的方式来随机检索数据。 你也可以sort()的ID列表(我相信MySQL检测到这一点,并跳过为你排序该列表。)

对于涉及物化视图(实质上缓存表)的大数据集和高请求率还有其他技术。正试图解决大型繁忙表格上的现有性能问题?

0

另一种选择是使用随机播种散列函数并对其进行排序。

检索表格的最大和最小ids,并使用PHP的rand()函数生成最大值和最小值之间的随机数。

然后使用该号码到种子你散列函数.Assume {盐}在SQL指由PHP

SELECT image FROM table 
WHERE image != '' 
ORDER BY MOD(ABS({salt}-id), MOD({salt}, 10)), ABS({salt}-id)); 

你可以优化比特执行所述MOD产生的随机整数({盐},10)在PHP中计算并在查询中传递值。

0

如果行大小不是很大,我只会选择50行并在应用程序中保留一个随机列表中的12行。是的,这意味着你扔掉了80%的选定行。当你说话的时候,有50%是真的是犯罪吗?这是SQL不擅长的事情。