#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
столбец.