【问题标题】:Why is MySQL returning the same results while using RAND() in the SELECT statement?为什么 MySQL 在 SELECT 语句中使用 RAND() 时返回相同的结果?
【发布时间】:2014-01-17 13:47:55
【问题描述】:

我打开了许多指向同一个自动刷新 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() 时返回相同的结果”有太多谷歌响应,通常指向使用 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>

【问题讨论】:

  • 对不起,php文件中的原始sql字符串确实有限制,问题正在发生。它应该是 $query = "SELECT * FROM customers WHERE customer_group='consumables' AND customer_updated

标签: php mysql mysqli


【解决方案1】:

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

【讨论】:

  • 我已经更新了我的问题以包含另一页上的代码部分并调用 PHP 脚本。它返回的结果与我之前得到的完全相同。 rand() 函数背后的种子看起来是我深入研究它的好地方。我不确定如何启用 SQL 日志记录,所以我也会这样做。感谢您对此的帮助。
  • 是否可以使用 PHP 生成随机种子放入 rand() 函数中?根据我的阅读(并略微理解),rand() 函数可以采用 0 到 1.0 之间的参数。那么我可以在 PHP 中生成一个 0 到 1.0 之间的随机数来强制执行此操作吗?
  • 感谢您对此事的帮助。由于一些烦人的缓存问题,我的测试让我望而却步,但这也确实很有帮助,为我节省了很多时间。
  • @SystemX17 试试我的更新,看看不同浏览器的查询是否真的一样。
【解决方案2】:

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

试试这个:

SELECT SQL_NO_CACHE *
       /* etc */

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

看到这个:http://dev.mysql.com/doc/refman/5.1/en/query-cache.html 它说,

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

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

【讨论】:

  • 我尝试使用“div workers”进行此操作,我现在已将其更新为原始问题并得到了相同的结果。虽然选定的客户似乎是随机的,但它在所有“div 工作人员”中都重复出现。
  • 一开始这似乎不起作用,但突然之间它开始起作用了。我猜缓存最终得到了排序。谢谢。
【解决方案3】:

你没有限制记录的数量,所以他只是带来了不同的订单,但你的哪里有相同的结果。尝试限制您的结果

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

【讨论】:

  • 抱歉,我弄错了,贴在这里的时候把那部分剪掉了。我会更新问题。
【解决方案4】:

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

【讨论】:

  • 对不起,我在粘贴到这个网站时切断了限制 10。我想知道最后遗漏了什么。它应该一次更新 10 个结果(因此我希望它们是随机的以防止“某些”重叠)。
  • 还是会去看看 shuffle 函数把我带到哪里。如果它像我认为的那样有效,那么它应该是甜蜜的。
  • 试试添加 SQL_NO_CACHE 是否可以解决您的问题? SELECT SQL_NO_CACHE * FROM customers WHERE customer_group='consumables' AND customer_updated
  • 我尝试使用“div workers”进行此操作,我现在已将其更新为原始问题并得到了相同的结果。虽然选定的客户似乎是随机的,但它在所有“div 工作人员”中都重复出现。
  • 您能否使用“customerdata_worker2.php”之类的 mysql 查询复制文件,在查询中都有 SQL_NO_CACHE 指令,假设一半的工作人员请求原始文件,而一半的工作人员请求重复文件?跨度>
猜你喜欢
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 2011-09-06
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
  • 2012-08-21
相关资源
最近更新 更多