【问题标题】:Where am I going wrong in using a Join in the mysql query - Explain result posted too在 mysql 查询中使用 Join 我哪里出错了 - 也发布了解释结果
【发布时间】:2013-03-15 01:21:15
【问题描述】:

我有这个查询大约需要 3.5 秒才能获取 2 条记录。但是,推荐信中有超过 100k 行,用户中有 13k 行,课程中有 850 行,考试中有 2 行。

SELECT t.*, u.name, f.feedback
FROM testmonials t
INNER JOIN user u ON u.id = t.userid
INNER JOIN courses co ON co.id = t.courseid
LEFT JOIN exam ex ON ex.id = t.exam_id
WHERE t.status = 4
AND t.verfication_required = 'Y'
AND t.verfication_completed = 'N'
ORDER BY t.submissiondate DESC

.解释结果:.

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  co  ALL     PRIMARY     NULL    NULL    NULL    850     Using temporary; Using filesort
1   SIMPLE  t   ref     CID,nuk_tran_user   CID     4   kms.co.id   8   Using where
1   SIMPLE  u   eq_ref  PRIMARY     PRIMARY     4   kms.t.userid    1   Using where
1   SIMPLE  ex  eq_ref  PRIMARY     PRIMARY     3   kms.t.eval_id   1   

如果我删除courses 表连接,那么查询会很快返回结果。我不明白为什么这个查询必须选择所有课程行,即 850?

任何想法我做错了什么?

编辑: 我在推荐表中的 courseid 和 userid 上有一个索引,这些是它们各自表的主键。

编辑 2

我刚刚从推荐表中删除了 courseid 索引(只是为了测试),有趣的是查询在 0.22 秒内返回了结果!!!??与上述相同的其他所有内容仅删除了此索引。

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  t   ALL     nuk_tran_user   NULL    NULL    NULL    130696  Using where; Using filesort
1   SIMPLE  u   eq_ref  PRIMARY     PRIMARY     4   kms.t.userid    1   Using where
1   SIMPLE  co  eq_ref  PRIMARY     PRIMARY     4   kms.t.courseid  1   
1   SIMPLE  ex  eq_ref  PRIMARY     PRIMARY     3   kms.t.exam_id   1   

编辑 3

编辑 3

CREATE TABLE IF NOT EXISTS `courses` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `description` text NOT NULL,
  `duration` varchar(100) NOT NULL DEFAULT '',
  `objectives` text NOT NULL,
  `updated_at` datetime DEFAULT NULL,
  `updated_by` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=851 ;


Testimonials


CREATE TABLE IF NOT EXISTS `testimonials` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `feedback` text NOT NULL,  
  `userid` int(10) unsigned NOT NULL DEFAULT '0',
  `courseid` int(10) unsigned NOT NULL DEFAULT '0',
  `eventid` int(10) unsigned NOT NULL DEFAULT '0',
  `emr_date` datetime DEFAULT NULL,
  `exam_required` enum('Y','N') NOT NULL DEFAULT 'N',
  `exam_id` smallint(5) unsigned NOT NULL DEFAULT '0',
  `emr_completed` enum('Y','N') NOT NULL DEFAULT 'N',
  PRIMARY KEY (`id`),
  KEY `event` (`eventid`),
  KEY `nuk_tran_user` (`userid`),
  KEY `emr_date` (`emr_date`),
  KEY `courseid` (`courseid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=134691 ;

.. 这是最新的 Explain 查询结果...

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  t   ALL     nuk_tran_user,courseid  NULL    NULL    NULL    130696  Using where; Using filesort
1   SIMPLE  u   eq_ref  PRIMARY     PRIMARY     4   kms.t.userid    1   Using where
1   SIMPLE  co  eq_ref  PRIMARY     PRIMARY     4   kms.t.courseid  1   
1   SIMPLE  ex  eq_ref  PRIMARY     PRIMARY     3   kms.t.exam_id   1   

【问题讨论】:

  • 你在courses.ID上有索引吗?
  • 是的,它在 testimonials 表中有索引,它是 course 表的主键。
  • 因为你看起来不像...
  • MYSQL做join的方式是先计算LEFT,然后再尝试join。所以切换到 RIGHT JOIN 将较大的表放在 where 子句dev.mysql.com/doc/refman/5.0/en/left-join-optimization.html
  • 有趣,它们是相同的数据类型吗?它没有在课程上使用任何键,也没有对连接进行昂贵的文件排序..

标签: mysql join explain


【解决方案1】:

已知执行没有可利用的相应索引的 ORDER BY 会导致延迟问题。即使这并没有具体回答您的课程表问题。

您的原始查询看起来几乎没问题,但是您引用了“f.feedback”并且查询中没有“f”别名。您还参考了“verification_required”和“verification_completed”,但在表结构中看不到它们,但确实找到了“exam_required”和“emr_completed”。

不过,我会改变一件事。在推荐表中,我将添加一个多列索引,而不是单个列索​​引,以同时利用您的多条件查询和 order by

create table ...
KEY StatVerifySubmit ( status, verification_required, verification_completed, submissionDate )

但您的查询似乎引用了表结构列表中未列出的列,但可能是

KEY StatVerifySubmit ( status, exam_required, emr_completed, emr_Date)

【讨论】:

    【解决方案2】:

    您能否尝试以下查询而不是原始查询:

    SELECT t.*, u.name, f.feedback
    FROM testmonials t
    INNER JOIN user u ON u.id = t.userid
    LEFT JOIN exam ex ON ex.id = t.exam_id
    WHERE t.status = 4
    AND t.verfication_required = 'Y'
    AND t.verfication_completed = 'N'
    AND t.courseid in ( SELECT co.id FROM courses co)
    ORDER BY t.submissiondate DESC
    

    您需要从课程表中选择列吗?

    【讨论】:

      猜你喜欢
      • 2011-05-31
      • 1970-01-01
      • 2023-03-11
      • 2016-05-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-17
      • 1970-01-01
      • 2021-04-18
      相关资源
      最近更新 更多