【问题标题】:Serious MySQL Performance Issue (Joins, Temporary Table, Filesort....)严重的 MySQL 性能问题(联接、临时表、文件排序......)
【发布时间】:2010-10-16 20:38:14
【问题描述】:

我有一个用户表和一个投票表。投票表存储对其他用户的投票。无论好坏,投票表中的一行存储两个用户之间双向的投票。

现在,问题是当我想列出某人投票过的所有人时。

我不是 MySQL 专家,但据我所知,由于 join 语句中的 OR 条件,它需要查看 整个 用户表(目前 +44,000 行),并为此创建一个临时表。

目前,下面的查询大约需要两分钟,是的,两分钟才能完成。如果我删除 OR 条件,以及 join 语句中它之后的所有内容,它会在不到半秒的时间内运行,因为它只需要查看 44,000 个用户行中的大约 17 个(explain ftw! )。

下面的例子,用户 ID 是 9834,我正在尝试获取他/她自己的 no 票,并加入被投票用户的信息看结果。

是否有更好、更快的方法来执行此查询?或者我应该重组表格吗?我非常希望可以通过修改查询来修复它,因为表中已经有很多用户 (+44,000) 和投票 (+130,000),我必须迁移它们。

谢谢:)

SELECT *, votes.id as vote_id 
FROM `votes` 
LEFT JOIN users ON (
  (
    votes.user_id_1 = 9834
    AND
    users.uid = votes.user_id_2
  )
  OR
  (
    votes.user_id_2 = 9834
    AND
    users.uid = votes.user_id_1
  )
)
WHERE (
  (
    votes.user_id_1 = 9834
    AND
    votes.vote_1 = 0
  )
  OR
  (
    votes.user_id_2 = 9834
    AND
    votes.vote_2 = 0
  )
)
ORDER BY votes.updated_at DESC
LIMIT 0, 10

【问题讨论】:

    标签: mysql database performance join temp-tables


    【解决方案1】:

    您可以执行 2 个查询的 UNION,而不是 OR。我知道在至少一个其他 DBMS 中这要快一个数量级的实例,我猜 MySQL 的查询优化器可能共享相同的“功能”。

    SELECT  whatever
    FROM    votes v
            INNER JOIN
                    users u
                    ON v.user_id_1 = u.uid
    WHERE   v.user_id_2 = 9834
    AND     v.votes_2 = 0
    
    UNION
    
    SELECT  whatever
    FROM    votes v
            INNER JOIN
                    users u
                    ON v.user_id_2 = u.uid
    WHERE   v.user_id_1 = 9834
    AND     v.votes_1 = 0
    
    ORDER BY updated_at DESC
    

    【讨论】:

    • 您能发布一个这样的查询示例吗?我远非 SQL 大师,所以看到一些实际代码非常有用:)。另外,是否仍然可以按 updated_at 列对结果进行排序,并为分页做限制/偏移?
    • 更好的是,如果不可能重复,请执行 UNION ALL(在这种情况下似乎是这样)。常规 UNION 强制进行排序和重复消除,在这种情况下不需要这样做。
    • 抱歉,我的浏览器一定是坏了,因为您的查询之前没有显示...哈哈,我只是试了一下,我似乎没有得到任何结果,但最大的问题是我似乎无法让 ORDER BY 工作,它只是抱怨 updated_at 列不存在。我也试过 v.updated_at。
    • 您需要在查询中返回 v.updated_at,在 ORDER BY 中只保留 update_at。
    • David:感谢您所做的一切,它会在眨眼间返回我需要的确切结果。但是,由于我在这里显然是个白痴,我如何返回 v.updated_at 以使 ORDER BY 工作?大声笑...是的,当涉及到 SQL 时,我是自学成才的,基于我何时需要它(不经常:P)...大声笑
    【解决方案2】:

    您已经回答了自己的问题:是的,您应该重新设计表格,因为它不适合您。它太慢了,并且需要过于复杂的查询。幸运的是,迁移数据本质上只是执行您在此处询问的查询,但对于所有用户,而不仅仅是一个用户。 (也就是说,对第一个答案建议的联合进行总和或计数。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-21
      • 1970-01-01
      • 2013-03-18
      • 1970-01-01
      • 2016-12-15
      • 2016-09-04
      • 2015-05-01
      相关资源
      最近更新 更多