Медленный запрос в MySQL с объединениями

#mysql #performance #join #foreign-keys

#mysql #Производительность #Присоединиться #внешние ключи

Вопрос:

У меня есть запрос, который выполняется слишком медленно, но я не могу понять причину этого или решение для него. Сначала выполнение запроса заняло около 22 секунд, но затем я попытался удалить внешний ключ из табличной книги, который является FK для ParentID в той же таблице. После этого удаления запрос занял около 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'
  

Количество строк в моей среде:

Ответ на запрос 3992125,
QuestionSession 367334,
AnswerTextMarker 9696,
QuestionGroup 18793,
ChapterGroupItemInChapterGroup 42360,
ChapterGroupBook 2297,
Книга 378

Ответ №1:

ChapterGroupBook выглядит как таблица сопоставления «многие ко многим». Если да, то почему все столбцы обнуляются? Создавайте их (и любые другие в другом месте) NOT NULL там, где это уместно.

Из-за вышесказанного в этой таблице нет PRIMARY KEY . Это плохо для InnoDB. Также смотрите мои многие: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 столбец.