我的查询运行速度太慢,但是我无法弄清其背后的原因或解决方案。该查询最初需要 22秒才能运行,但是随后我尝试删除表Book中的外键,该表是同一表中对ParentID的FK。删除之后,查询大约需要 1秒。这固然很好,但是应该有更多改进的余地,无论是重组查询本身还是使用不同的索引。
有人可以建议吗?为什么Book.ParentID的外键会导致查询时间增加呢?最好的方法是什么,尝试重写查询或查看索引?
除了将外键放到Book.ParentID
之外,我尝试在所选表和某些联接上使用use index
,但运气不佳。
这是一个小提琴:http://sqlfiddle.com/#!9/7f7bbb/9
但是,小提琴中的解释计划与我在生产中提出的计划有所不同。这是从生产开始的解释计划(带有Book.ParentID的外键):
'1','SIMPLE','Bk',NULL,'index_merge','PRIMARY,fk_CategoryParent_ID_idx','PRIMARY,fk_CategoryParent_ID_idx','8,9',NULL,'2','100.00','Using union(PRIMARY,fk_CategoryParent_ID_idx); Using where; Using temporary; Using filesort'
'1','SIMPLE','CGB2',NULL,'ref','uq_ChapterGroup_Category,book_chaptergroup_unique_row_constraint,fk_Category_ChapterGroup_ID,ix_chapterGroupBook_chapterGroupID','book_chaptergroup_unique_row_constraint','9','Hypo.Bk.ID','8','100.00','Using where'
'1','SIMPLE','CCG2',NULL,'ref','uq_ChapterID_ChapterGroupItemInChapterGroup,uq_ExamID_ChapterGroupItemInChapterGroup,fk_ChapterGroup_Chapter_ID,ix_chapterChapterGroup_chapterID','fk_ChapterGroup_Chapter_ID','8','Hypo.CGB2.ChapterGroupID','2','100.00','Using where'
'1','SIMPLE','ATM',NULL,'ref','PRIMARY,fk_Chapter_AnswerTextMarker_ID,fk_QuestionGroup_AnswerTextMarker_ID','fk_Chapter_AnswerTextMarker_ID','8','Hypo.CCG2.ChapterID','5','100.00','Using where'
'1','SIMPLE','QG',NULL,'eq_ref','PRIMARY','PRIMARY','8','Hypo.ATM.QuestionGroupID','1','100.00','Using index'
'1','SIMPLE','AQS',NULL,'ref','PRIMARY,fk_AQSession_AnswerTextMarker_ID,ix_answerQuestionSession_questionSessionID','fk_AQSession_AnswerTextMarker_ID','8','Hypo.ATM.ID','313','100.00',NULL
'1','SIMPLE','QS',NULL,'eq_ref','PRIMARY,fk_QSession_User_ID,ix_QuestionSession_userId_type_sessionDate','PRIMARY','8','Hypo.AQS.QuestionSessionID','1','5.00','Using where'
我的环境中的行数:
AnswerQuestionSession 3992125
QuestionSession 367334
AnswerTextMarker 9696
QuestionGroup 18793
ChapterGroupItemInChapterGroup 42360
ChapterGroupBook 2297
图书378
答案 0 :(得分:0)
ChapterGroupBook
看起来像一个多对多映射表。如果是这样,为什么所有列都可以为空?使它们(以及其他任何地方的其他东西)NOT NULL
适当。
由于上述原因,该表没有PRIMARY KEY
。这对InnoDB不利。另请参阅我的many:many tips。
OR
是性能杀手。有什么方法可以避免在(Bk.ID=551 OR Bk.ParentID=551)
中使用它?如有必要,我们在派生表中使用UNION
:
FROM ( ( SELECT id FROM Book WHERE id = 551 )
UNION ALL
( SELECT id FROM Book WHERE parent_id = 551 ) )
JOIN ...
(使用了“索引合并”,但可能会慢一些。)
请重新格式化EXPLAIN
,以便我可以清楚地看到Rows
列。