2011-10-14 162 views
1

我有4个表MYSQL连接查询优化与多tablesU

类,考试,问题意识,UserResponses

Class -> ID , Name 
Exam -> ID,Name,Class_ID_FK 
Questions -> ID,Question,Exam_ID,FK 
Answers -> ID,Answer,Question_ID_Fk 
UserResponses -> ID,UserID,Answer_ID_fk,Question_ID_fk 

我想获取所有用户寄托给定class.I都的所有考试写了一个查询,但我想看看别人的建议,如果我正确的方向走,因为这个查询的500个实例可能同时在我的系统中运行。

select r.answer_id_fk,r.userid,q.question,a.answer,e.name,e.class_id_fk 
from Exams e 
join Questions q on q.exam_id_fk = e.id 
join Answers a on a.question_id_fk = q.id 
left join UserResponses r on r.answer_id_fk = a.id 
where e.class_id_fk =105585; 

我认为这最终会经历数据库中的所有行,最终可能会崩溃。

解释显示了这一点。它返回了35行,这是正确的。我在问题表中有18091行.20423在回答中。并在答案中为'67108'。

1, SIMPLE, a, ALL, , , , , 67108, 
1, SIMPLE, q, eq_ref, PRIMARY, PRIMARY, 25, db_qa_dev.a.question_id_fk, 1, 
1, SIMPLE, c, eq_ref, PRIMARY, PRIMARY, 25, db_qa_dev.q.category_id_fk, 1, Using where 
1, SIMPLE, r, ref, ANSWERID_INDEX, ANSWERID_INDEX, 26, db_qa_dev.a.id, 15, Using index 
+4

这不是租赁编码器 - 显示你已经完成了一些工作。 –

+1

如何发布您的查询?然后我们可以提出更多的建议。 – Bojangles

+0

@JamWaffles已发布查询。 –

回答

2

解释计划出来的方式,它看起来像你的一个外键索引缺失。 MySQL引擎应该寻找最佳查询计划,这通常意味着从索引上过滤最多的数据开始并从那里开始工作。我不知道实际数据的外观如何,但我猜想e.class_id_fk上的限制应该是相当严格的,所以引擎可能会先过滤掉这些行。那么,因为你的所有参与者都包含简单的FK/PK关系,所以它只会加入其他表中的单行。

我能想到的唯一原因是为什么它可能不这样做是因为其中一个表中的数据真的很棘手(例如,Exam中的每一行都具有相同的class_id_fk值),或者您缺少您的FK专栏中的索引。

缺少FK列上的索引可能会使优化程序决定更换不同的路由比每隔JOIN必须扫描该表更快。在大多数情况下,您总是需要在所有FK上使用索引,因为这些列往往倾向于JOIN,因此索引对于读取非常有用。

+0

感谢您的详细解释。此链接可能有助于某人。 http://hackmysql.com/case4 –

1

如果您在表格上强制使用最少匹配的straight_join,则查询速度应该更快。
请注意,只能使用straight_join替换内部联接,因为左侧联接不会减少结果集中的行数。

不是100%确定,因为您的解释select与您的查询不符。

SELECT r.answer_id_fk,r.userid,q.question,a.answer,e.name,e.class_id_fk 
FROM Exams e 
STRAIGHT_JOIN Questions q ON (e.class_id_fk = '105585' AND q.exam_id_fk = e.id) 
STRAIGHT_JOIN Answers a on a.question_id_fk = q.id 
LEFT JOIN UserResponses r on r.answer_id_fk = a.id 
+0

我试过了STRAIGHT_JOIN,并表明它可以优化查询和其他方式。我使用它后,没有海峡加入索引,它工作正常,但它只是简单地忽略了我的索引。 –