基本上我正在尝试提取一个用户尚未从数据库响应的随机轮询问题。这个查询大约需要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',如果重要的话。
任何建议都将不胜感激。
答案 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)
他建议(在此示例中用引号替换引号)
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的建议对我来说很好。