严重的MySQL性能问题(连接,临时表,Filesort ....)

时间:2009-04-01 12:43:22

标签: mysql database performance join temp-tables

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

现在,问题在于我想列出一些人投票的所有人。

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

目前,bellow查询大约需要两分钟,是,两分钟才能完成。如果我在join语句中删除OR条件及其后面的所有内容,它会在不到半秒的时间内运行,因为它只需要查看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

2 个答案:

答案 0 :(得分:6)

您可以执行UNION of 2查询,而不是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

答案 1 :(得分:0)

你已经回答了自己的问题:是的,你应该重新设计表格,因为它不适合你。它太慢了,需要过于复杂的查询。幸运的是,迁移数据只是基本上要处理您在这里询问的问题,而是针对所有用户而不仅仅是一个。 (也就是说,第一次回答建议的工会的总数或数量。)