MySQL меняет порядок условий в WHERE. Как обойти?

sergej-123

Новичок
Добрый день,

Столкнулся с проблемой, что mysql меняет порядок условий в WHERE.

Есть база:
PHP:
CREATE TABLE IF NOT EXISTS `con` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `cid` int(11) NOT NULL,
  `cdate` date NOT NULL,
  `type` smallint(6) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `IDX_CID` (`cid`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

INSERT INTO `con` (`id`, `cid`, `cdate`, `type`) VALUES
(2, 2, '2011-08-11', 1),
(3, 3, '2011-06-01', 2),
(4, 4, '2011-06-15', 2);

CREATE TABLE IF NOT EXISTS `hist` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_con` int(11) NOT NULL,
  `update` date NOT NULL,
  PRIMARY KEY (`id`),
  KEY `IDX_CON` (`id_con`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

INSERT INTO `hist` (`id`, `id_con`, `update`) VALUES
(1, 2, '2011-08-29'),
(2, 2, '2011-08-01'),
(3, 2, '2011-07-20'),
(4, 3, '2011-06-08'),
(5, 4, '2011-06-23');
Выполняем запрос:
PHP:
explain SELECT
	c.cdate,
	c.type,
	h.id_con,
	max(h.update)    AS `update`,
	date_ymd         AS max_update,
	n                AS `month`
FROM
	con c,
	hist h,
	(
		SELECT '2011-08-25' AS date_ymd, 0 AS n
		UNION SELECT '2011-07-31', 1
		UNION SELECT '2011-06-30', 2
	) AS `month`
WHERE 
	c.cid = 2 AND
	h.id_con = c.id AND
	`update`<= date_ymd
GROUP BY 
	id_con, date_ymd;

Видим следующее


Uploaded with ImageShack.us

Т.е. всё по индексам проходит, всё ОК. Выполняем запрос и смотрим как mysql его преобразовывает
PHP:
explain extended SELECT
	c.cdate,
	c.type,
	h.id_con,
	max(h.update)    AS `update`,
	date_ymd         AS max_update,
	n                AS `month`
FROM
	con c,
	hist h,
	(
		SELECT '2011-08-25' AS date_ymd, 0 AS n
		UNION SELECT '2011-07-31', 1
		UNION SELECT '2011-06-30', 2
	) AS `month`
WHERE 
	c.cid = 2 AND
	h.id_con = c.id AND
	`update`<= date_ymd
GROUP BY 
	id_con, date_ymd;

MySQL отдает, и собственно пытается выполнить, вот такой запрос:
PHP:
select 
	`test`.`c`.`cdate` AS `cdate`,
	`test`.`c`.`type` AS `type`,
	`test`.`h`.`id_con` AS `id_con`,
	max(`test`.`h`.`update`) AS `update`,
	`month`.`date_ymd` AS `max_update`,
	`month`.`n` AS `month` 
from 
	`test`.`con` `c` 
join 
	`test`.`hist` `h` 
join (
	select '2011-08-25' AS `date_ymd`,0 AS `n` 
	union select '2011-07-31' AS `2011-07-31`,1 AS `1` 
	union select '2011-06-30' AS `2011-06-30`,2 AS `2`
) `month` 
where (
	(`test`.`c`.`id` = `test`.`h`.`id_con`) and 
	(`test`.`c`.`cid` = 2) and 
	(`test`.`h`.`update` <= `month`.`date_ymd`)
) 
group by 
`test`.`h`.`id_con`,`month`.`date_ymd`

Как видим MySQL поменял очередность условий в WHERE (1 и 2 условие), что не очень хорошо сказывается на больших объемах данных.
Пробовал в запросе в WHERE брать условия в скобки () чтобы указать очередность, но толку нет, всё равно MySQL именно так преобразовывает. Что делать?
 

akd

dive now, work later
Команда форума
"Т.е. всё по индексам проходит, всё ОК." и Using temporary, using filesort как у вас вместе сочетаются только не совсем понятно :)
 

zerkms

TDD infected
Команда форума
порядок условий в WHERE ни на что никогда не влиял. mysql выполняет так, как соптимизирует
 

whirlwind

TDD infected, paranoid
Он не where меняет, а порядок использования индексов в джойне. Для таких случаев может помочь явное STRAIGHT JOIN ON (с указанием условий), но не факт что для юнионов проканает.
 
Сверху