Как оптимизировать запрос в MySQL при JOIN выборке по условиям из обеих таблиц?

Здравствуйте. Есть 2 таблицы:
CREATE TABLE IF NOT EXISTS `queries` (
  `id` int(8) unsigned NOT NULL AUTO_INCREMENT,
  `query` varchar(32) NOT NULL,
  `state` enum('valid','invalid','reserv') NOT NULL,
  `used` enum('client_1','client_2','client_3','nobody') NOT NULL,
  PRIMARY KEY (`id`),
  KEY `state` (`state`,`used`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `queries_states` (
  `id` int(8) unsigned NOT NULL AUTO_INCREMENT,
  `query_id` int(8) unsigned NOT NULL,
  `act` enum('search','save','prepares') NOT NULL,
  `sub_state` enum('ok','error') NOT NULL,
  `last_use` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `query_id` (`query_id`,`act`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

Таблицы содержат по 30к записей и их количество будет увеличиваться.
Задача состоит в том, чтобы максимально быстро выбрать строку из таблицы queries которая соответствует условию:
SELECT SQL_NO_CACHE * FROM queries q JOIN queries_states s ON q.id = s.query_id WHERE q.state = 'valid' and q.used = 'nobody' and s.act = 'search' and s.sub_state = 'ok'  ORDER BY s.last_use  LIMIT 1


Этот запрос отлично за 0.0000 сек отрабатывает, если не использовать ORDER BY s.last_use(а это условие - выборки именно самого старого запроса - обязательно). При использовании ORDER BY s.last_use, начинается Using temporary; Using filesort. Если JOIN'ить, например, через STARIGHT_JOIN сначала queries_states, а потом queries и создать индекс в queries_states по last_use, то запрос отрабатывает за 0,0050 сек, но хотелось бы быстрее.
Как я понимаю, проблема в том, что MySQL не умеет использовать индексы для выборки при JOIN'e.

Прошу мне помочь с моей проблемой. Индексы на второй таблице, кроме уникального (`query_id`,`act`) убрал сознательно, так как без STRAIGHT_JOIN толку от них никакого. Если нужно, поставлю какие скажите.
  • Вопрос задан
  • 2993 просмотра
Решения вопроса 1
@Shahelm
Можно попробовать добавить индексы:
queries_states: по полям (act, sub_state, last_use) - один индекс
queries : по полям (state, used) - один индекс
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы