[英]MySQL slow query using filesort
我在使用MySQL查询时遇到速度问题。 这些表的定义如下:
CREATE TABLE IF NOT EXISTS `student` (
`student_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`forename` varchar(30) NOT NULL,
`updated_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`surname` varchar(50) NOT NULL,
`student_college` int(11) DEFAULT NULL,
`countup` smallint(5) unsigned DEFAULT NULL,
PRIMARY KEY (`student_id`),
KEY `countup` (`countup`),
KEY `student_sort` (`countup`,`updated_time`),
KEY `student_college` (`student_college`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
和
CREATE TABLE IF NOT EXISTS `college` (
`college_id` int(11) NOT NULL AUTO_INCREMENT,
`college_name` varchar(100) NOT NULL DEFAULT 'Centre Name',
`college_location` int(11) DEFAULT NULL,
PRIMARY KEY (`college_id`),
KEY `college_location` (`college_location`),
KEY `college_name` (`college_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
查询如下:
SELECT *
FROM student
JOIN college ON student.student_college = college.college_id
WHERE
college_location = 1
ORDER BY student.countup desc, student.updated_time desc
LIMIT 15;
我得到以下解释:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE college ref "PRIMARY,college_location" college_location 5 const 915 Using where; Using temporary; Using filesort
1 SIMPLE student ref student_college student_college 5 speed_test.college.college_id 50 Using where
“学生”表具有约500,000条记录,“大学”表具有915行。 第三个表用于存放学院的所有位置。 我的查询需要检索特定位置的所有学生,然后按countup和updated_time对结果进行排序。 我有一个关于countup和updated_time的综合索引。 我想摆脱文件排序,但是我找不到令人满意的方法。
我考虑过将college_location
移到student表中,以便可以将其合并为一个复合索引。 有更好的解决方案吗?
下面的查询将删除“使用临时”; 使用文件排序。 从解释上来说,这样应该更有效。
MySQL优化器是愚蠢的,因此诀窍在于强制优化器是您想要的,并且这是一个基于college.college_location = 1的派生表。因此,您可以将结果与Student表进行内连接。 这样,MySQL可以使用排序键
SELECT
*
FROM
student
INNER JOIN (
SELECT
college_id
FROM
college
WHERE
college.college_location = 1
) college
ON student.student_college = college.college_id
ORDER BY
student.countup DESC
, student.updated_time DESC
注意大写锁定中的新索引
参见演示http://sqlfiddle.com/#!2/05c8a/1
或者,如果您认为它更有意义或更易于阅读,则可以使用它。 性能应该是相同的,因为解释向我解释了它是相同的。
SELECT
*
FROM (
SELECT
college_id
FROM
college
WHERE
college.college_location = 1
)
college
INNER JOIN
student
ON
student.student_college = college.college_id
ORDER BY
student.countup DESC
, student.updated_time DESC
参见演示http://sqlfiddle.com/#!2/05c8a/23
新的策略分治法将更多查询发送到数据库,这将使用正确的索引。 并且不需要临时表和文件排序。
SET @college_ids = NULL;
SELECT
GROUP_CONCAT(college_id)
FROM
college
WHERE
college_location = 1
GROUP BY
college_location ASC
INTO @college_ids;
SELECT
*
FROM
student
WHERE
student.student_college IN(@college_ids)
ORDER BY
student.countup DESC
, student.updated_time DESC
;
我很难对此进行测试,但是请尝试使用此student_sort
密钥:
KEY
student_sort (
student_college ,
counting DESC ,
updated_time DESC)
尝试索引:
KEY student_sort(countup DESC ,updated_time DESC)
然后使用STRAIGHT_JOIN和FORCE INDEX:
SELECT *
FROM student force index(student_sort) STRAIGHT_JOIN
college
ON student.student_college = college.college_id
WHERE college_location = 1
ORDER BY student.countup desc,
student.updated_time desc
LIMIT 15;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.