繁体   English   中英

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

[英]Why is MySQL returning the same results while using RAND() in the SELECT statement?

我打开了许多浏览器窗口,它们指向相同的自动刷新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>

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返回相同的结果集。

不太确定,但是由于您的查询中没有LIMIT,所以我认为从查询中删除速度非常慢的ORDER BY RAND()部分并在mysql查询结果中使用php函数shuffle可能是个好主意。

您并没有限制记录的数量,因此,他只会带来不同的订单,但是在您所在的位置却获得相同的结果。 尝试限制您的结果

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

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

尝试这个:

SELECT SQL_NO_CACHE *
       /* etc */

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM