2011-12-22 58 views
0

我已相对于阅读速度问题通过MySQL和PHP得到一个随机行,不知道怎么我的代码可能速度得到改善。我的优化排随机取

我在一个名为“旗帜”表数据库欢迎信息,我想显示相对于页面上的位置随机的横幅,并添加+1到VIEW_COUNT为这面旗帜。我的方法可行,但对于每次页面加载都会发生这种情况的繁忙网站,这可以提高速度吗?由于

/* Get banners for position 1 then choose a random one to display */ 
$banners = mysql_query("SELECT id,title,banner_url,destination FROM ".TBL_BANNERS." WHERE position = '1' AND status = '1'"); 
$banner_count = mysql_num_rows($banners) - 1; 
$rand_offset = mt_rand(0,$banner_count); 
$result = mysql_query("SELECT id,title,banner_url,destination FROM ".TBL_BANNERS." LIMIT $rand_offset, 1 "); 

$banner_id = mysql_result($result,0,"id"); 
$banner_title = mysql_result($result,0,"title"); 
$banner_url = mysql_result($result,0,"banner_url"); 
$banner_dest = mysql_result($result,0,"destination"); 

/* Add view to this banner */ 
$database->addViewToBanner($banner_id); 

最后一个函数使用查询:

"UPDATE banners SET view_count = view_count+1 WHERE id = '$banner_id'" 

我还需要多说,有可能不会成为任何超过100条记录中的“横幅”表在任何一个时间,但有会在ID中漏洞。这些ID可能会上升到200,但只有一半仍然存在。

+2

对不起,有什么不对劲的错'ORDER BY RAND()LIMIT 1'(实际上可能什么不对的地方,我不是sarky,实际上,我问)? – DaveRandom 2011-12-22 16:57:44

+0

我读过,当你在桌子上有洞的时候,这种方式并不是随机的。比如我现在的ID返回了原来的查询是9,15和16 – user29660 2011-12-22 17:06:46

+0

@DaveRandom是 - 做一个ORDER BY RAND()是资源密集型的,您注意到了很多更与数千个/百万行的表。国际海事组织(IMO)在只有相对较少的行的表上使用它仍然很好。见http://www.titov.net/2005/09/21/do-not-use-order-by-rand-or-how-to-get-random-rows-from-table/一个不错的解释。 – Nick 2011-12-22 17:09:02

回答

1

生成PHP中的随机数和钻这种方式进入PK

的SQL将

SELECT id,title,banner_url,destination 
FROM TBL_BANNERS 
WHERE id = $rand_offset 

如果你错过了,再次运行。这给出了一个非常有效的寻求一个行,这将是比使用极限更好/偏移处理

+0

好的小费。我使用mysql_result从随机行中获取ID,并在第二个查询中使用该ID。谢谢 – user29660 2011-12-22 17:12:19

+0

如果你已经有了一个随机的行(为了得到ID),那么你不需要第二个'SELECT'来获取其余的数据 - 当你获取ID时你可能会得到这些数据。问题在于如何首先获得随机行。 – Amadan 2011-12-22 17:26:53

+0

但原始查询用于确保我抓取正确的记录,而不是表中的每个记录(WHERE position ='1'AND status ='1')。还有一些记录被删除,所以我不能随便选择一行。 – user29660 2011-12-22 17:36:31

0

代替第一SELECT的,使用此:

$banners_count_result = mysql_query("SELECT COUNT(*) AS num_banners FROM ".TBL_BANNERS." WHERE position = '1' AND status = '1'"); 
$banner_count = mysql_result($banners_count_result, 0, "num_banners"); 

除非你添加和删除新的横幅每隔几秒钟,考虑某处缓存这个结果。

+0

这肯定会使效率降低,因为该查询只会返回1条信息(行数)?如果我使用这个,我不会有一个随机ID使用,所以它会使第二个查询更复杂。 – user29660 2011-12-22 17:18:53

+0

该查询为您提供总行数。然后在PHP中生成一个1到现在的行数的随机数,在第二个查询中,像前面那样使用LIMIT构造拉整行。无论如何你都在做两个查询,但你的第一个(选择所有行,请求计数)的效率非常低。这个人做同样的事情,但以一种非常有效的方式(选择行数,得到单个结果行)。 – Amadan 2011-12-22 17:25:46

+0

我会想用PHP来计算行数比使用MYSQL方法更快,但我可能是错的。即使即时通讯错误,它仍然会使第二个查询效率降低,因为我必须使用偏移LIMIT而不是仅仅是“WHERE ID =”子句。 – user29660 2011-12-22 17:47:51

1

做到这一点,最理想的方式,你可以在很多地方在互联网,例如阅读Anton Titov's blog是做2个查询:

SELECT COUNT(*) AS banners FROM quotes 

然后生成您的编程语言中的随机数(即PHP使用mt_rand)。并将其输入到此查询中:

SELECT * FROM banners LIMIT $generated_number, 1 

注意:如果您的表只有少量的行,则不适用。一般来说,我仍然使用ORDER BY RAND(),直到我知道表中会有超过100行。

+0

所以多个查询不总是一件坏事?那么完整的横幅表在任何时候都不会有超过50条记录,所以也许我更有效地使用ORDER BY RAND解决方案。 – user29660 2011-12-22 17:25:29

+0

并非总是如此。通常在处理IN(),NOT IN()或RAND()时,最好做第二个查询。 – Nick 2011-12-22 17:32:18