为什么MySQL在SELECT语句中使用RAND()时会返回相同的结果?

时间:2014-01-17 13:47:56

标签: php mysql mysqli

我打开了许多浏览器窗口,指向同一个自动刷新的PHP页面。它访问MySQL数据库以识别过期的客户信息。特别是获取最近一天未更新的记录并强制更新。其余的代码似乎处理得很好。

这是我的MySQLi查询:

$query = "SELECT *
          FROM customers
          WHERE customer_group='consumables' AND customer_updated < DATE_SUB(NOW(), INTERVAL 1 DAY)
          ORDER BY RAND()
          LIMIT 10";

我被告知RAND()不是很合适,因为它对大型表的处理速度很慢,但是在这个项目结束之前我的表不会增加到超过20000。我还有一个随机变量传递给URL,如“clientdataupdates.php?nocachepls = 1541231”。

所以这是我的问题:在当前的5000多条记录中,如果这个脚本同时在多个浏览器窗口中运行,它们将获得从MySQL返回的相同记录。不可否认,所选记录似乎是随机挑选的,但如果查询在同一时间运行,则会在所有窗口中返回相同的记录。

我的研究受到以下事实的限制:我一直在寻找的关键词(现在几天)似乎与其他问题有关,例如“php mysql在使用rand()时返回相同的结果”有太多的google响应指向一般使用rand()。

虽然我仍然感谢任何帮助,但实际上我更想知道为什么会这样。我对MySQL内部工作原理的了解是有限的,但是对于我与PHP和MySQL连接的所有经验,我没有看到任何类似的事情发生。

更新:

我还测试了使用ajax函数,该函数包含一个回调函数来重新启动它。每次div内容都是相同的记录 - 但它仍然看起来像是随机选择哪条记录。

<div id='worker1' class='workerDiv'>worker: waiting..</div>
<div id='worker2' class='workerDiv'>worker: waiting..</div>
<div id='worker3' class='workerDiv'>worker: waiting..</div>
<div id='worker4' class='workerDiv'>worker: waiting..</div>
<div id='worker5' class='workerDiv'>worker: waiting..</div>
<script>
 function nextWorker(thisWorker){
  setTimeout(function(){ ajaxpage('customerdata_worker.php',thisWorker,nextWorker(thisWorker)); }, 10000);
 }
 setTimeout(nextWorker('worker1'), 100);
 setTimeout(nextWorker('worker2'), 100);
 setTimeout(nextWorker('worker3'), 100);
 setTimeout(nextWorker('worker4'), 100);
 setTimeout(nextWorker('worker5'), 100);
</script>

4 个答案:

答案 0 :(得分:2)

Rand()种子

当没有第二个值时,MySQL使用系统时钟播种RAND()。种子值以微秒为单位,我无法重现RAND()生成相同值两次的问题。

如果您打开MySQL Workbench并同时执行两个语句。每个输出都不同。

SELECT RAND();
SELECT RAND();

当您打开多个标签并获得相同的结果时。这可能是一个缓存问题,但是您声明要标记URL以防止缓存。因此,在服务器上启用SQL日志记录并验证是否正在调用新查询。

Rand()表现

ORDER BY RAND()很慢,因为它需要MySQL来读取整个表。即使ORDER BY RAND() LIMIT 1仍需要MySQL来读取整个表格。

<强>更新

您可以看到SQL正在生成的随机值。

$query = "SELECT *, RAND() AS `X`
          FROM customers
          WHERE customer_group='consumables' AND customer_updated < DATE_SUB(NOW(), INTERVAL 1 DAY)
          ORDER BY `X`
          LIMIT 10";

这将包括每行的X列。用于对查询进行排序的随机值。将其添加到输出中,看看每个浏览器是否真正从MySQL返回相同的结果集。

答案 1 :(得分:1)

不太确定,但由于你的查询中没有LIMIT,我认为从查询中删除那个非常慢的ORDER BY RAND()部分并简单地在结果上使用php函数shuffle是个好主意mysql查询。

答案 2 :(得分:1)

你并没有限制记录的数量,因此他只会带来不同的订单,但是同样的结果会出现在你的位置。尝试限制结果

$query = "SELECT * FROM customers WHERE customer_group='consumables' AND customer_updated < DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY RAND() LIMIT 10";

答案 3 :(得分:1)

您可能正在某些结果集中从MySQL查询缓存中接收信息。

试试这个:

SELECT SQL_NO_CACHE *
       /* etc */

注意:将SQL_NO_CACHE字放在与SELECT和*(或您选择的第一列的名称)相同的行上。

请参阅:http://dev.mysql.com/doc/refman/5.1/en/query-cache.html它说,

  

查询缓存存储SELECT语句的文本   发送给客户端的相应结果。如果相同   稍后收到语句,服务器从中检索结果   查询缓存而不是再次解析和执行语句。该   查询缓存在会话之间共享,因此一个结果集生成   可以发送客户端以响应另一个发出的相同查询   客户端。

专业提示:在软件中避免使用SELECT *。在结果集中提供所需列的名称。