Где я ошибаюсь, используя соединение в запросе mysql. Объясните опубликованный результат.

У меня есть этот запрос, который занимает около 3,5 секунд, чтобы получить 2 записи. Однако в отзывах более 100 000 строк, среди пользователей — 13 000, в курсах — 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?

Любые идеи, что я делаю неправильно?

Изменить: у меня есть индекс для курса, идентификатор пользователя в таблице отзывов, и это первичные ключи соответствующих таблиц.

РЕДАКТИРОВАТЬ 2

Я только что удалил индекс курса из таблицы отзывов (просто для проверки), и, что интересно, запрос вернул результат за 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 ;

.. это последний результат запроса объяснения на данный момент ...

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   

person user1421214    schedule 25.03.2013    source источник
comment
у вас есть индекс на courses.ID?   -  person John Woo    schedule 25.03.2013
comment
да, у него есть индекс в таблице отзывов и первичный ключ таблицы курсов.   -  person user1421214    schedule 25.03.2013
comment
Потому что не похоже, что у тебя...   -  person Tony Hopkinson    schedule 25.03.2013
comment
способ, которым MYSQL выполняет соединения, заключается в том, чтобы сначала вычислить LEFT, а затем попытаться выполнить соединения. Поэтому переключитесь на ПРАВОЕ СОЕДИНЕНИЕ, поместив большие таблицы в предложение where dev.mysql.com/doc/refman/5.0/en/left-join-optimization.html   -  person Waygood    schedule 25.03.2013
comment
Интересно, это один и тот же тип данных? Он не использует никаких ключей на курсах и выполняет дорогостоящую сортировку файлов для соединения.   -  person Tony Hopkinson    schedule 25.03.2013
comment
@Waygood - не могли бы вы опубликовать пример запроса - просто образец. Спасибо   -  person user1421214    schedule 25.03.2013
comment
@Waygood. ооооооооооооооооооооооооооооооочень не приятно   -  person Tony Hopkinson    schedule 25.03.2013
comment
@TonyHopkinson - Да, тот же тип данных - столбец courseid в таблице отзывов имеет значение int (10), UNSIGNED   -  person user1421214    schedule 25.03.2013
comment
Пожалуйста, опубликуйте схему (как в экспорте CREATE TABLE) для таблицы курсов.   -  person Captain Payalytic    schedule 25.03.2013
comment
Я думаю, JW спрашивал, есть ли у вас индекс ID в таблице COURSES. Можете ли вы показать DDL для всех четырех таблиц?   -  person BellevueBob    schedule 25.03.2013
comment
См. Редактирование 2. Теперь я удалил индекс курсов - удаление этого индекса заняло 5 секунд. Я просто подумал повторить этот запрос (без индекса), но он выполнился быстрее! как странно!!   -  person user1421214    schedule 25.03.2013
comment
@BellevueBob - Да, я могу подтвердить, что course.id является первичным ключом.   -  person user1421214    schedule 25.03.2013
comment
Пожалуйста, сделайте так, как попросили несколько из нас, и опубликуйте определения таблиц!   -  person Captain Payalytic    schedule 25.03.2013
comment
@CaptainPayalytic - см. РЕДАКТИРОВАТЬ 3 ... Я снова добавил индекс ..   -  person user1421214    schedule 25.03.2013
comment
Я не понимаю, почему вы оставили соединение с экзаменом - на мой взгляд, это соединение не нужно?   -  person Del Pedro    schedule 25.03.2013
comment
@DelPedro - извините, мне нужно присоединиться к этому, так как мне также нужно запросить некоторые значения из этой таблицы. В приведенном выше запросе есть тип, поскольку он должен быть e.feedback вместо f.feedback.   -  person user1421214    schedule 25.03.2013
comment
@DelPedro, извините, снова плохо - я просто проверяю изменения, которые я вношу, и отвечаю здесь ... в любом случае, я обновил Edit 3, вы можете видеть, что последний - это идентификатор курса   -  person user1421214    schedule 25.03.2013
comment
Может быть, я что-то упускаю (не в первый раз)... Но откуда берутся столбцы t.status, t.verfication_required, t.verfication_completed и t.submissiondate? Я не видел их в запросе CREATE TABLE...   -  person jerdiggity    schedule 29.03.2013
comment
вы когда-нибудь решали это? Он по-прежнему указан как не принятый ответ.   -  person DRapp    schedule 01.08.2013
comment
Вам нужно обновить другие таблицы, даже с предоставленной информацией, когда вы предоставляете нам DDL для своих таблиц, в которых нет строк в вашем запросе, который нужно оптимизировать - мы не можем помочь.   -  person cerd    schedule 11.08.2013


Ответы (2)


Известно, что выполнение ORDER BY без соответствующего индекса, который можно использовать, вызывает проблемы с задержкой. Хотя это конкретно не отвечает на ваш вопрос о таблице курсов.

Ваш исходный запрос выглядит ПОЧТИ нормально, но вы ссылаетесь на "f.feedback" и в запросе нет псевдонима "f". Вы также ссылаетесь на «verification_required» и «verification_completed», но не видите их в структурах таблиц, но ДЕЙСТВИТЕЛЬНО находите «exam_required» и «emr_completed».

Однако я бы изменил одну вещь. В таблице отзывов вместо индексов отдельных столбцов я бы добавил еще один с несколькими столбцами, чтобы использовать преимущества вашего запроса с несколькими критериями И порядок по

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

но похоже, что ваш запрос относится к столбцам, не указанным в списке структуры вашей таблицы, но вместо этого может быть

KEY StatVerifySubmit ( status, exam_required, emr_completed, emr_Date)
person DRapp    schedule 06.04.2013

Не могли бы вы попробовать следующий запрос вместо оригинала:

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

Вам нужно выбрать столбцы из таблицы курсов?

person Thierry Marianne    schedule 31.03.2013