【问题标题】:Display 10 Random Rows from MySQL Table w/ PHP使用 PHP 从 MySQL 表中显示 10 个随机行
【发布时间】:2020-04-23 14:46:33
【问题描述】:

我对此进行了大量研究,但找不到适合我情况的答案。

我经营一个网站,其中大约 10,000 种产品的详细信息存储在 MySQL 数据库中。这个数字一直在增加,最终可能会达到 20,30 或 40,000 种产品。

我正在重新设计网站,作为其中的一部分,我想展示存储产品的表格中的 10 个随机产品。理想情况下,我想添加分页,如果您愿意,您可以滚动浏览所有 10,000 种产品 - 但分页不是问题。

我找不到从 MySQL 表中获取随机行的有效方法。我已经看到很多提到 RAND() 但它对于超过 100 行的任何东西都非常慢。我已经尝试过诸如根据条目数生成随机数并以此拉动-但这并不能说明是否删除了一行然后找不到结果。这也意味着我必须为 10 个随机行运行该语句 10 次。

我考虑过将所有行存储到一个数组中,然后随机抽取 10 行。但是,每次用户访问此页面时,将最少 10,000 行存储到一个数组中似乎也效率低下。

有人对最好的方法有什么建议吗?我知道我没有在这里发布任何实际代码,但那是因为我没有任何代码。我尝试过的每种方法都不能满足我的需要,或者速度非常慢。

任何建议将不胜感激:(

编辑;我正在运行的使用 Rand() 需要 18 秒的 SQL 查询是:

SELECT Title,Price,Img,Seller,Positive,Negative,Neutral,Glowing,PD,STOCK,StoreItems.ItemURL,Currency,Verified, BTC, ETH, LTC, PayPal, Stripe, Stores.Verified FROM Stores JOIN StoreItems On Stores.StoreID = StoreItems.StoreID INNER JOIN Promotions ON StoreItems.ItemURL = Promotions.ItemID INNER JOIN Gateway ON StoreItems.ItemURL = Gateway.ItemURL WHERE Stores.Verified = 'true' ORDER BY RAND() LIMIT 5

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    您可以使用 PHP rand 生成 10 个伪随机值并尝试匹配 ID

    $r = [];
    for ($i = 0; $i<10;$i++) {$r[] = rand(0, NUM_OF_PRODUCTS);}
    $stmt = $conn->prepare("SELECT 1 FROM products WHERE id IN (?,?,?,?,?,?,?,?,?,?)");
    $stmt->bind_param('iiiiiiiiii', $r[], $r[1], $r[2], $r[3], $r[4], $r[5], $r[6], $r[7], $r[8], $r[9]);
    

    【讨论】:

    • 谢谢 - 如果 ID 不存在,例如它被删除了吗?我想也许在数据库中搜索一个小于产品数量的随机 id。如果 num_rows > 0 那么它会将结果添加到一个数组中,并在 count($array)
    • @miknik 答案可能更适合这种情况。
    【解决方案2】:

    定义超慢。

    我刚刚使用以下查询从 304,096 行执行时间为 0.123327 秒的表中随机抽取了 50 行:

    SELECT *
    FROM `calendar`
    ORDER BY RAND()
    LIMIT 50;
    

    使用此查询衡量的性能:

    SET profiling = 1;
    SELECT *
    FROM `calendar`
    ORDER BY RAND()
    LIMIT 50;
    SELECT query_id, SUM(duration)
    FROM information_schema.profiling
    GROUP BY query_id
    ORDER BY query_id
    DESC LIMIT 3;
    

    【讨论】:

    • 我刚刚用 Rand() 运行了我的查询并得到以下信息:查询耗时 18.0547 秒。我猜这是一个更复杂的查询。它从 3 个单独的表和一些不同的检查中提取数据。所以这可能是让兰德如此缓慢的原因。
    • 也许您可以将随机顺序的核心选择放入临时表中。然后对临时表进行所有复杂的连接。所以先做随机部分并存储它,然后再做所有复杂的查询。希望页面的“随机”部分能像 304,096 个日历条目示例一样快。
    • @Yanfly 这就是为什么您需要在问题中发布您实际所做的事情 - 当我们看不到您的实际问题时,实际上不可能调试您的问题代码。
    • 我发布了我正在运行的 SQL 查询,我试图在其中提取 5 个随机条目 - 希望这会有所帮助。
    【解决方案3】:

    我会通过一个 UPDATE 查询每天或每小时为它们分配一个随机数,例如 1 到 10,000。

    UPDATE products SET static_random = FLOOR(RAND()*10000)
    

    因此,不是每次都获得随机分配,而是按计划完成“随机性”。 (或者只使用介于 0 和 1 之间的默认 RAND())然后在页面上,使用 PHP ($randomPosition}) 在同一范围内选择一个随机数,然后从 MySQL 返回类似:

    SELECT * FROM products WHERE static_random > {$randomPosition} 
    ORDER BY static_random ASC LIMIT 10
    

    所以它会在随机选择的位置之后选择接下来的 10 个“随机”项目。如果返回的机会少于 10,则选择另一个随机位置。

    根据您运行 cron 的频率,它可能不是完全随机的,但它似乎足够随机,因为我认为从 10,000 个数字中选择相同范围的 10 个数字的机会足够小。

    还有其他方法可以随机分配分配的静态随机数而不是 cron。也许在页面访问中随机有 100 次机会,在一个 UPDATE 查询中再次为它们分配所有随机数(绝对不是单独的 UPDATE 查询)。或者在刚刚挑选的 10 个中,为它们生成一个新的静态随机数,这样每次都会在随机点将一小批“重新洗牌”回到牌组中。

    或者,您总是可以选择按静态随机数排序的前 10 个项目,而不是使用随机位置。总是从第一个位置开始。这可能有助于分页每次获得相同的“随机”结果集。

    此外,对于选择的那些项目,您可以生成新的随机数,可能在较高范围的一端。这样,他们就会走向“堆栈的末端”,并且在其他项目轮到之前不太可能再次被选中。不过,在某些时候你可能不得不重新洗牌。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-24
      • 1970-01-01
      • 2011-05-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多