【发布时间】: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
-
有趣,它们是相同的数据类型吗?它没有在课程上使用任何键,也没有对连接进行昂贵的文件排序..