2013-03-20 6 views
-1

Запрос занимает слишком много времени. Этот запрос поступает из веб-приложения. это повлияло на нашу производительность. Кто-нибудь, пожалуйста, помогите мне переписать его и поделиться со мной своими ценными предложениями.Запрос занимает слишком много времени и влияет на нашу производительность.

запрос с Explain Plan:

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

Избегайте 'DISTINCT'. Почему вы используете 'IN', если возможно только одно значение? Попробуйте заменить подвыборки на соединения. У вас есть индексы на столбцах, которые вы фильтруете? – Kai

+0

, пожалуйста, пришлите мне этот запрос. – pvr

+0

В соответствии с вашим самым последним вопросом, пожалуйста, старайтесь избегать того, чтобы люди переписывали ваши запросы для вас - гораздо лучше попросить помощи, а затем применить полученный вами совет. – halfer

ответ

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. Но я надеюсь, что это даст вам представление о том, как решить эту проблему.

Чтобы дать более удобный ответ, просто уберите свой пост с таблицами и данными или создайте sqlfiddle и объясните, что вы пытаетесь достичь из этой таблицы и как вы относитесь к ним.

EDIT:

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 
+0

@pvr, я отредактировал мое сообщение и удостоверился в вещах, упомянутых в «Заметке». Если проблема по-прежнему сохраняется, то укажите свои таблицы в http://sqlfiddle.com. –

+0

Здесь вы можете найти ссылку на скрипт sql. http://www.sqlfiddle.com/#!2/b1b57/4 – pvr

+0

Обновите sqlfiddle с помощью некоторых фиктивных данных. Попробуйте часть запроса, представленную в EDIT2 –

Смежные вопросы