【问题标题】:Problems with ORDER BY RAND() and big tablesORDER BY RAND() 和大表的问题
【发布时间】:2020-10-08 15:48:44
【问题描述】:

你好我今天早上问了一个问题,我意识到问题不是我在找的地方 (here the original question)

我有这个查询可以从地址簿中随机生成注册表。

SELECT * FROM address_book ab 
            WHERE 
            ab.source = "PB" AND 
            ab.city_id = :city_id AND 
            pb_campaign_id = :pb_campaign_id AND 
            ab.id NOT IN (SELECT address_book_id FROM calls WHERE calls.address_book_id = ab.id AND calls.status_id IN ("C","NO") OR (calls.status_id IN ("NR","OC") AND TIMESTAMPDIFF(MINUTE,calls.updated_at,NOW()) < 30))
            ORDER BY RAND()
            LIMIT 1';

但我注意到“按 rand () 排序”需要超过 50 秒,并且在大型表 (100k +) 上使用高达 25-50% 的 CPU,所以我在这里寻找解决方案,但我没有找到任何有效的方法。 注意:id 不是自增的,可能会有差距

有什么想法吗?

【问题讨论】:

  • 请定义效果不太好
  • @GMB 已编辑,抱歉。
  • 您需要仅使用 SQL 的解决方案,还是可以使用其他语言来帮助解决这个问题?
  • @TomRevell SQL 更好,但(如果可能)php 解决方案是有效的

标签: mysql sql mariadb innodb


【解决方案1】:

我建议这样写:

SELECT *
FROM address_book ab 
WHERE ab.source = 'PB' AND 
      ab.city_id = :city_id AND 
      pb_campaign_id = :pb_campaign_id AND 
      NOT EXISTS (SELECT 1
                  FROM calls c
                  WHERE c.address_book_id = ab.id AND
                        ( c.status_id IN ('C', 'NO') OR
                         (c.status_id IN ('NR', 'OC') AND c.updated < now() - interval 30 minute)
                        ) 
                )

ORDER BY RAND()
LIMIT 1;

请注意,这会更改相关子查询中的逻辑,因此c.address_book_id = ab.id 始终适用。我怀疑这是性能问题。

然后,在以下位置创建索引:

  • address_book(source, city_id, campaign_id, id)
  • calls(address_book_id, status_id, updated)

我猜这足以提高性能。如果碰巧有无数行符合条件,那么order by rand() 可能是个问题。

【讨论】:

  • 谢谢!我发现问题是“calls.address_book_id = ab.id”
【解决方案2】:
  1. 我绝不会建议在庞大的数据库中进行子查询,因为它需要很长的执行时间。
  2. 使用正确的索引,如果需要使用内连接(切勿使用左连接)
  3. 如果可能,请在 php 脚本中使用您的业务逻辑,因为您的数据库可能会更大,并且执行此类查询需要花费太多时间。
  4. 如果您只希望大型数据库中的一个数据不要使用rand() 函数,请取任意rand 数(1 到数据库行数)并使用限制limit skip,number 例如。 limit 2,1 它只给第 3 行 希望它有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    • 1970-01-01
    相关资源
    最近更新 更多