У меня проблемы с оптимизацией этого запроса:
SELECT a.id
FROM a
JOIN b ON a.id=b.id
LEFT JOIN c ON a.id=c.id
WHERE
(b.c1='12345' OR c.c1='12345')
AND (a.c2=0 OR b.c3=1)
AND a.c4='active'
GROUP BY a.id;
Запрос занимает 7 с, тогда как 0, когда только один из b
или c
СОЕДИНЯЕТСЯ. ОБЪЯСНЕНИЕ:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: a
type: ref
possible_keys: PRIMARY(id),c4,c2
key: c4
key_len: 1
ref: const
rows: 80775
Extra: Using where; Using temporary; Using filesort
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: c
type: ref
possible_keys: id_c1_unique,id
key: id_c1
key_len: 4
ref: database.a.id
rows: 1
Extra: Using index
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: b
type: ref
possible_keys: id_c1_unique,id,c1,c3
key: id
key_len: 4
ref: database.a.id
rows: 2
Extra: Using where
Всегда есть ровно 1 подходящая строка из b
и самое большее одна подходящая строка из c
. Было бы намного быстрее, если бы MySQL начинал с получения строк b
и c
, которые совпадают с литералом c1
, затем соединял бы a
на основе id
, но вместо этого он начинался с a
.
подробности:
- MyISAM
- Все столбцы имеют индексы (_уникальные УНИКАЛЬНЫЕ)
- Все столбцы НЕ НУЛЬЫ
Что я пробовал:
- Изменение порядка соединения
- Перемещение условий WHERE в пункты ON
- Подвыбирает для
b.c1
и c.c1
(WHERE b.id = (ВЫБЕРИТЕ b.id ИЗ b, ГДЕ c1 = '12345'))
- ИНДЕКС ИСПОЛЬЗОВАНИЯ для
b
и c
Я понимаю, что мог бы сделать это, используя два SELECT с UNION, но мне нужно избегать этого, если это вообще возможно, из-за того, как генерируется запрос.
Редактировать: Добавить CREATE TABLEs
CREATE TABLE
с соответствующими столбцами.
CREATE TABLE `a` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`c2` tinyint(1) NOT NULL,
`c4` enum('active','pending','closed') NOT NULL,
PRIMARY KEY (`id`),
KEY `c2` (`c2`)
KEY `c4` (`c4`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `b` (
`b_id` int(11) NOT NULL AUTO_INCREMENT,
`id` int(11) NOT NULL DEFAULT '0',
`c1` int(11) NOT NULL,
`c3` tinyint(1) NOT NULL,
PRIMARY KEY (`b_id`),
UNIQUE KEY `id_c1_unique` (`id`,`c1`),
KEY `c1` (`c1`),
KEY `c3` (`c3`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `c` (
`c_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`id` int(11) NOT NULL,
`c1` int(11) NOT NULL,
PRIMARY KEY (`c_id`),
UNIQUE KEY `id_c1_unique` (`id`,`c1`),
KEY `id` (`id`),
KEY `c1` (`c1`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8;