查询耗时太长。此查询来自Web应用程序。 它影响了我们的表现。请帮助我改写它并与我分享您宝贵的建议。
使用解释计划查询:
mysql> explain SELECT DISTINCT(tab2.idnum) FROM (`tab2`) JOIN `tab1` ON tab1.question = tab2.idnum WHERE `department` = 'Biology' AND tab2.status != 'active' AND tab2.status != 'retired' AND (tab2.instructor = 164604 OR tab2.instructor = 194703) AND tab1.topic IN (SELECT `topic` FROM (`tab5`) JOIN `tab4` ON tab4.chapter = tab5.id WHERE `book` = 1000) AND tab2.idnum NOT IN (SELECT `question` FROM (`tab3`) WHERE `book` = 1000 AND `isPR` = 1) AND `questiontype` IN ('mult') limit 2;
+----+--------------------+-----------------+-----------------+------------------+---------+---------+-------------------------------+--------+-------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-----------------+-----------------+------------------+---------+---------+-------------------------------+--------+-------------------------------------------+
| 1 | PRIMARY | tab1 | index | question | tq | 8 | NULL | 149899 | Using where; Using index; Using temporary |
| 1 | PRIMARY | tab2 | eq_ref | PRIMARY | PRIMARY | 4 | comp1.tab1.question | 1 | Using where |
| 3 | DEPENDENT SUBQUERY | tab3 | unique_subquery | qb,question,book | qb | 8 | func,const | 1 | Using where |
| 2 | DEPENDENT SUBQUERY | tab4 | ref | chapter,topic | topic | 4 | func | 1 | |
| 2 | DEPENDENT SUBQUERY | tab5 | eq_ref | PRIMARY | PRIMARY | 4 | comp1.tab4.chapter | 1 | Using where |
+----+--------------------+-----------------+-----------------+------------------+---------+---------+-------------------------------+--------+-------------------------------------------+
5 rows in set (0.00 sec)
表格结构:
mysql> show create table tab5\G
*************************** 1. row ***************************
Table: tab5
Create Table: CREATE TABLE `tab5` (
`name` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
`descrip` mediumtext NOT NULL,
`category` varchar(255) NOT NULL DEFAULT '',
`order` int(11) NOT NULL DEFAULT '0',
`department` varchar(255) NOT NULL DEFAULT '',
`book` int(11) NOT NULL DEFAULT '0',
`id` int(11) NOT NULL AUTO_INCREMENT,
`is_trial` tinyint(1) NOT NULL DEFAULT '0',
`is_live` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6305 DEFAULT CHARSET=latin1
mysql> show create table tab4\G
*************************** 1. row ***************************
Table: tab4
Create Table: CREATE TABLE `tab4` (
`chapter` int(11) NOT NULL DEFAULT '0',
`topic` int(11) NOT NULL DEFAULT '0',
KEY `chapter` (`chapter`),
KEY `topic` (`topic`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> show create table tab3\G
*************************** 1. row ***************************
Table: tab3
Create Table: CREATE TABLE `tab3` (
`question` int(11) NOT NULL,
`book` int(11) NOT NULL,
`isPR` tinyint(1) unsigned NOT NULL DEFAULT '0',
UNIQUE KEY `qb` (`question`,`book`),
KEY `question` (`question`),
KEY `book` (`book`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> show create table tab2 \G
*************************** 1. row ***************************
Table: tab2
Create Table: CREATE TABLE `tab2` (
`idnum` int(11) NOT NULL AUTO_INCREMENT,
`questiontype` enum('mult','CM','GO','FIB','AUD','HS','DD') NOT NULL DEFAULT 'def1',
`question` mediumtext NOT NULL,
`difficulty` int(3) DEFAULT '0',
`createdby` int(11) NOT NULL DEFAULT '0',
`createdwhen` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`status` enum('active','calibrating','onhold','retired') NOT NULL DEFAULT 'def1',
`parent` int(11) NOT NULL DEFAULT '0',
`child` int(11) NOT NULL DEFAULT '0',
`family` int(11) NOT NULL DEFAULT '0',
`department` varchar(255) NOT NULL DEFAULT '',
`notes` text NOT NULL,
`instructor` int(11) NOT NULL DEFAULT '0',
`nmfilter` enum('everyone','majors only','undetermined') NOT NULL DEFAULT 'def1',
`PR` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`idnum`),
KEY `family` (`family`)
) ENGINE=InnoDB AUTO_INCREMENT=186724 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> show create table tab1\G
*************************** 1. row ***************************
Table: tab1
Create Table: CREATE TABLE `tab1` (
`question` int(11) NOT NULL DEFAULT '0',
`topic` int(11) NOT NULL DEFAULT '0',
KEY `question` (`question`),
KEY `topic` (`topic`),
KEY `tq` (`topic`,`question`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
答案 0 :(得分:2)
这是一个很难分析的问题。尝试创建sql小提琴,以更好地了解您的问题。 我的建议是,尝试仅使用JOIN重写查询(删除嵌套查询)并尝试执行以下查询,
SELECT tab2.idnum
FROM (`tab2`) INNER JOIN `tab1` ON tab1.question = tab2.idnum INNER JOIN `tab3` ON tab2.idnum != tab3.question INNER JOIN `tab5` ON tab1.topic = tab5.topics
INNER JOIN `tab4` ON tab4.chapter = tab5.id
WHERE
tab5.department = 'Biology' AND tab2.status != 'active' AND tab2.status != 'retired' AND
(tab2.instructor = 164604 OR tab2.instructor = 194703)
AND tab5.book = 1000 AND tab3.book = 1000 AND tab3.isPR = 1
AND tab2.questiontype IN ('mult')
注意:由于我不确定你想要实现什么,我删除了一些像DISTINCT,LIMIT这样的东西。但我希望这能让你了解如何解决这个问题。
要提供更多的apporiate答案,只需使用表格和数据更新您的帖子或创建sqlfiddle并解释您要从这些表格中实现的目标以及如何将它们联系起来。
编辑:
SELECT tab2.idnum
FROM (`tab2`) INNER JOIN `tab1` ON tab1.question = tab2.idnum AND (tab2.status != 'active' AND tab2.status != 'retired' AND (tab2.instructor = 164604 OR tab2.instructor = 194703) AND tab2.questiontype IN ('mult'))
INNER JOIN `tab3` ON tab2.idnum != tab3.question AND tab3.book = 1000 AND tab3.isPR = 1
INNER JOIN `tab5` ON tab1.topic = tab5.topics AND tab5.department = 'Biology' AND tab5.book = 1000
INNER JOIN `tab4` ON tab4.chapter = tab5.id
注意:要提高速度,请确保索引,表中存在多少行并限制查询结果。
EDIT2:
SELECT tab2.idnum
FROM `tab2` INNER JOIN `tab1` ON tab1.question = tab2.idnum AND (tab2.status != 'active' AND tab2.status != 'retired' AND (tab2.instructor = 164604 OR tab2.instructor = 194703) AND tab2.questiontype IN ('mult'))
INNER JOIN `tab3` ON tab2.idnum != tab3.question AND tab3.book = 1000 AND tab3.isPR = 1
INNER JOIN `tab5` ON tab5.department = 'Biology' AND tab5.book = 1000
INNER JOIN `tab4` ON tab4.chapter = tab5.id
WHERE tab1.topic = tab4.topic