3

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

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

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

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

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

有没有更好、更快的方法来做这个查询?或者我应该重组表格吗?我非常希望可以通过修改查询来修复它,因为表中已经有很多用户(+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
4

2 回答 2

6

代替 OR,您可以执行 2 个查询的 UNION。我知道在至少一个其他 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
于 2009-04-01T12:46:20.303 回答
0

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

于 2009-04-01T23:53:01.963 回答