То, что нередко использование SQL_CALC_FOUND_ROWS более затратно, чем банальное COUNT(*) - это я знаю. Но я не ожидал, что это может быть настолько чудовищно затратно. Итак, имеем простенькую таблицу:
CREATE TABLE `aab` (
`id` int(10) UNSIGNED NOT NULL,
`user_id` int(10) UNSIGNED NOT NULL
`created_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB;
ALTER TABLE `aab`
ADD PRIMARY KEY (`id`),
ADD KEY `created_at` (`created_at`);
ALTER TABLE `aab`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
В таблице около 100К записей. Нам нужно получать постранично записи с сортировкой по полю
`created_at`. Делаем запрос:
EXPLAIN SELECT SQL_CALC_FOUND_ROWS id
FROM aab ORDER BY created_at DESC LIMIT 0, 20
Видим, что используется индекс
created_at, в rows вполне ожидаемо получаем все сто тыщ строк:
Добавляем в запрос поле, которое, казалось бы, ни на что не должно влиять:
EXPLAIN SELECT SQL_CALC_FOUND_ROWS id, user_id
FROM aab ORDER BY created_at DESC LIMIT 0, 20
И видим, что индекс уже не используется, и идет перебор по всем записям "в сухую":
В результате выборка выполняется почти на два порядка дольше. Как так? Почему? Можно ли это как-то побороть? Или тупо забить и все запросы переписывать под COUNT(*)?