Выборка последних записей из большой таблицы

23.05.2010 21:24 / Артём Волк / 1362 просмотра / ...

К примеру, в MySQL БД есть такая таблица:

`log`
----------
`id`			(номер записи в логе)
`inserted`		(дата и время события)
`message`		(описание события)
`user_id`		(вторичный ключ на таблицу пользователей `users`)

По логике приложения важным является выбрать последние записи из этой таблицы для каждого пользователя и вывести их на страницу. Сообщений в между очисткой/архивацией таблицы собирается много (до полумиллиона). Конечно можно сохранять в отдельную таблицу интересующие записи, но есть решение и на чистом SQL (работающее до определённого количества записей, конечно :)).

Первой мыслью было использование подзапроса:

SELECT 
	* 
FROM `log` 
LEFT JOIN `users` ON `users`.`id` = `log`.`user_id`
WHERE `id` IN 
(
	SELECT MAX(`id`) FROM `log` GROUP BY `user_id`
)

К сожалению, EXPLAIN показывает, что подзапрос выполняется больше одного раза (DEPENDENT QUERY). Можно, конечно, выполнить два отдельных запроса, но есть и более красивый вариант:

SELECT
  `log`.*,
  `users`.*
FROM
  `log`
INNER JOIN
  (
	SELECT
	  `user_id`, MAX(`id`) AS `maxid`
	FROM
	  `log`
	GROUP BY
	  `user_id`
	) as `temp`
ON
  `log`.id = `temp`.`maxid`
LEFT JOIN `users` ON `users`.`id` = `log`.`user_id`

В этом варианте тоже используется подзапрос, но выполняется он только один раз. Для максимально быстрой работы способа необходим индекс по полям user_id и id. Решение было подсказано в ответе на вопрос на StackOverflow.com.