Имеются две таблицы:
CREATE TABLE `messages` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`TOPIC` int(11) NOT NULL DEFAULT '0',
`MEMBER` int(11) NOT NULL DEFAULT '0',
`subject` tinytext,
`poster` tinytext NOT NULL,
`Email` tinytext,
`Time` bigint(20) DEFAULT NULL,
`body` text,
PRIMARY KEY (`ID`),
KEY `TOPIC` (`TOPIC`),
KEY `MEMBER` (`MEMBER`),
KEY `Time` (`Time`)
) ENGINE=InnoDB AUTO_INCREMENT=1351047 DEFAULT CHARSET=cp1251
и
CREATE TABLE `lenta` (
`ID` int(11) NOT NULL,
`sticky` tinyint(4) NOT NULL DEFAULT '0',
`subject` tinytext NOT NULL,
`annotation` tinytext,
`annotatedBy` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `sticky` (`sticky`)
) ENGINE=InnoDB DEFAULT CHARSET=cp1251
В этой таблице пока всего одна запись.
Запрос
EXPLAIN SELECT STRAIGHT_JOIN m.ID, annotatedBy FROM messages m LEFT JOIN lenta l ON m.ID = l.ID ORDER BY m.ID limit 5;
приводит к такому результату
+----+-------------+-------+-------+---------------+----------+---------+------+--------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+----------+---------+------+--------+----------------------------------------------------+
| 1 | SIMPLE | m | index | NULL | TOPIC | 4 | NULL | 924710 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | l | ALL | PRIMARY | NULL | NULL | NULL | 1 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+-------+---------------+----------+---------+------+--------+----------------------------------------------------+
Такой запрос выполняется неэффективно и долго.
Однако если убрать поле из запроса из второй таблицы,
EXPLAIN SELECT STRAIGHT_JOIN m.ID FROM messages m left JOIN lenta l ON m.ID = l.ID ORDER BY m.ID LIMIT 5;
то
+----+-------------+-------+--------+---------------+---------+---------+------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+------------------------+------+-------------+
| 1 | SIMPLE | m | index | NULL | PRIMARY | 4 | NULL | 5 | Using index |
| 1 | SIMPLE | l | eq_ref | PRIMARY | PRIMARY | 4 | mydatabase.m.ID | 1 | Using index |
+----+-------------+-------+--------+---------------+---------+---------+------------------------+------+-------------+
Или
EXPLAIN SELECT STRAIGHT_JOIN m.ID, l.ID FROM messages m left JOIN lenta l ON m.ID = l.ID ORDER BY m.ID LIMIT 5;
также выполняется нормально.
Т.е. если из второй таблицы запрашивать что угодно кроме полей, имеющими индекс, приводит к неэффективному выполнению запроса.
Кстати, первый вариант запроса, но без ORDER BY
выполняется хоть и неэффективно согласно explain, но вроде как быстро без explain:
EXPLAIN SELECT STRAIGHT_JOIN m.ID, l.annotatedBy FROM messages m LEFT JOIN lenta l ON m.ID = l.ID LIMIT 25;
+----+-------------+-------+-------+---------------+----------+---------+------+--------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+----------+---------+------+--------+----------------------------------------------------+
| 1 | SIMPLE | m | index | NULL | TOPIC | 4 | NULL | 924710 | Using index |
| 1 | SIMPLE | l | ALL | PRIMARY | NULL | NULL | NULL | 1 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+-------+---------------+----------+---------+------+--------+----------------------------------------------------+
Собственно, почему так? Почему запрос столбцов из таблицы справа приводит к неэффективному выполнению запроса?