数据库设计/ SQL优化:WHERE <id> NOT IN(数千个ID)</id>

时间:2012-04-19 12:45:13

标签: mysql performance database-design optimization

我被要求向应用程序添加功能,允许用户在两​​个选项之间进行投票:A和B.这些问题的表格非常基本:

QUESTIONS
question_id (PK)
option_id_1(FK)
option_id_2(FK)
urgent (boolean)

每次用户投票时,用户投票的内容都存储在同样简单的表格中:

USER VOTES
vote_id (PK)
user_id (FK)
question_id (FK)

当用户请求新问题时,选择出现哪个问题的算法很复杂,但出于我们的目的,我们可以假设它是随机的。那么,问题呢?

每个用户都会对许多问题进行投票。可能有数百甚至数千。我需要确保没有用户被提出他们已经投票的问题,而我猜想的唯一方法是,我猜测,将服务器置于遗忘状态。具体来说,如:

SELECT * from questions WHERE question_id NOT in (SELECT question_id from user_votes WHERE user_id = <user_id>) ORDER BY RAND() LIMIT 1. 

[注意:RAND()实际上并不在查询中 - 它只是替代稍微复杂的(order_by)。]

所以,请记住,许多用户很可能已经投票了数百甚至数千个问题,并且不可能按照既定顺序提出问题...任何关于如何排除投票问题的想法击败我的服务器?

所有建议都表示赞赏 - 非常感谢。

2 个答案:

答案 0 :(得分:3)

JOIN运算符比MySQL中的嵌套查询执行得更好(可能已经更新了最新的MySQL版本,但是如果遇到性能问题,我猜我的语句仍然存在)

你可以做的只是将联票投票留在问题上,只挑选那些没有投票的记录(没人投票):

SELECT * 
FROM questions q 
LEFT JOIN user_votes uv ON 
  uv.question_id = q.question_id AND
  uv.user_id = '<user_id>'
WHERE vote_id IS NULL

答案 1 :(得分:1)

RAND()很讨厌但是这可以减轻问题,同时为您提供所需的结果。看到你已经提到RAND()就是一个例子,我实际上无法提供比下面更具体的建议,但是替换ORDER BY应该可以正常工作。

您可以越多地限制内部查询中的行数,整个查询的执行速度就越快。

SELECT
    q.*
FROM (
    -- First get the questions which have not been answered
    SELECT 
        questions.*
    FROM questions 
    LEFT JOIN user_votes 
        ON user_votes.question_id = questions.question_id
        AND user_votes.user_id = <user_id>
    WHERE user_votes.user_id IS NULL
) q
-- Now get a random 1.  I hate RAND().
ORDER BY RAND()
LIMIT 1
相关问题