mysql - MySQL 中使用连接的慢查询

标签 mysql performance join foreign-keys

我有一个查询运行速度太慢,但我无法找出其背后的原因或解决方案。该查询一开始运行大约需要 22 秒,但随后我尝试删除表 Book 中的一个外键,该外键是同一个表中 ParentID 的 FK。删除此操作后,查询大约需要1 秒。这当然很好,但应该还有更多改进的空间,要么重组查询本身,要么使用不同的索引。

有人可以建议吗?为什么 Book.ParentID 的外键会导致查询时间增加如此之多?这里最好的方法是什么,尝试重写查询或查看索引?

除了将外键删除到 Book.ParentID 之外,我还尝试在所选表和一些联接上使用use index,但没有真正的运气。

这是一个 fiddle :http://sqlfiddle.com/#!9/7f7bbb/9

但是, fiddle 中的解释计划与我在生产中得到的解释计划不同。这是生产中的解释计划(带有 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'

我的环境中的行数:

回答问题 session 3992125
问题 session 367334
答案文本标记 9696
问题群18793
ChapterGroupItemInChapterGroup 42360 第2297章群书
书 378

最佳答案

ChapterGroupBook 看起来像一个多对多映射表。如果是这样,为什么所有列都可以为空?在适当的情况下将它们(以及其他地方的任何其他内容)设为NOT NULL

由于上述原因,该表没有主键。这对 InnoDB 来说是不好的。另请参阅我的many:many tips

OR 是性能 killer 。有什么方法可以在 (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列。

关于mysql - MySQL 中使用连接的慢查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55489364/

相关文章:

php - 今天 PDO 是否转义 "%"和 "_"

mysql - 内部 JOIN 缺少行

django - 配置 uwsgi 服务器以提高性能

php - 运行高负载 php 文件而不损害服务器性能

sql - T-SQL,计划作业中的多个更新

mysql - 计算每个帐户组的记录数量,其中加入日期 = 每个月

mysql - 如何在具有条件的第二个表上使用分组依据时从左表中检索所有数据

hadoop - 将多个 Hive 表合并为 Hadoop 中的单个表

sql - 甲骨文 SQL : Add sum from another table to query results

mysql - 两个 MySQL 表的最佳连接