Медленный запрос в MySQL с объединениями - PullRequest
0 голосов
/ 03 апреля 2019

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

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

AnswerQuestionSession 3992125
QuestionSession 367334
AnswerTextMarker 9696
QuestionGroup 18793
ChapterGroupItemInChapterGroup 42360
ChapterGroupBook 2297
Книга 378

1 Ответ

0 голосов
/ 21 апреля 2019

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

Из-за вышеизложенного в этой таблице нет PRIMARY KEY. Это плохо для InnoDB. Также см. Мой много: много советов .

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.

...