SQL左连接查询运行非常慢

时间:2009-10-15 23:29:21

标签: sql mysql optimization

基本上我正在尝试提取一个用户尚未从数据库响应的随机轮询问题。这个查询大约需要10-20秒才能执行,这显然不行!响应表大约是30K行,数据库也有大约300个问题。

SELECT  questions.id
FROM  questions
LEFT JOIN  responses ON ( questions.id = responses.questionID
AND responses.username =  'someuser' ) 
WHERE
responses.username IS NULL 
ORDER BY RAND() ASC 
LIMIT 1

问题和响应表的PK是'id',如果重要的话。

任何建议都将不胜感激。

5 个答案:

答案 0 :(得分:11)

您很可能需要

上的索引
responses.questionID
responses.username 

如果没有索引搜索30k行总是很慢。

答案 1 :(得分:4)

这是一种不同的查询方法,可能更快:

SELECT q.id
FROM questions q
WHERE q.id NOT IN (
    SELECT r.questionID
    FROM responses r
    WHERE r.username = 'someuser'
)

确保r.username上有一个索引,而且应该非常快。

以上将返回所有未答复的问题。要选择随机的,你可以使用低效(但很简单)ORDER BY RAND() LIMIT 1,或者使用Tom Leys建议的方法。

答案 2 :(得分:3)

问题可能不是连接,它几乎可以肯定按顺序排序30k行rand()

答案 3 :(得分:3)

请参阅:Do not order by rand

他建议(在此示例中用引号替换引号)

SELECT COUNT(*) AS cnt FROM quotes

-- generate random number between 0 and cnt-1 in your programming language and run 
-- the query:

SELECT quote FROM quotes LIMIT $generated_number, 1

当然你可能会在第二个声明中将第一个声明作为子选择。

答案 4 :(得分:0)

OP是否确定原始查询返回正确的结果集?

我假设添加了“AND responses.username ='someuser'”子句以加入规范,其意图是连接将仅为某些用户未应答的id生成空的右侧列。

我的问题:加入不会为每个问题生成空的右侧列。所有用户都没有回答过问题。左连接的工作原理是,“如果目标表中的任何行与连接表达式不匹配,则会为SELECT列列表中的目标表的所有列引用生成NULL值。”

无论如何,nickf的建议对我来说很好。