Как оптимизировать запрос с помощью GROUP BY и ORDER BY - PullRequest
2 голосов
/ 08 марта 2011

У меня есть таблица POSTS, структура выглядит следующим образом:

CREATE TABLE IF NOT EXISTS `posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) COLLATE utf8_turkish_ci DEFAULT NULL,
  `content` longtext COLLATE utf8_turkish_ci,
  `excerpt` longtext COLLATE utf8_turkish_ci,
  `link` longtext COLLATE utf8_turkish_ci,
  `original_link` longtext COLLATE utf8_turkish_ci,
  `mime_type` longtext COLLATE utf8_turkish_ci,
  `language_id` int(11) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  `site_id` int(11) DEFAULT NULL,
  `type` varchar(255) COLLATE utf8_turkish_ci DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `modified_at` datetime DEFAULT NULL,
  `is_deleted` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  KEY `type` (`type`),
  KEY `created_at` (`created_at`),
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci AUTO_INCREMENT=52487 ;

И таблица USERS, построенная так:

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) COLLATE utf8_turkish_ci NOT NULL,
  PRIMARY KEY (`id`),
  KEY `username` (`username`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci AUTO_INCREMENT=9422 ;

Я использую этозапрос, чтобы получить последние сообщения "страница, файл или сообщение", упорядоченные по убыванию времени и группировке по пользователю, чтобы не показывать все последние сообщения пользователя:

   SELECT p.*, u.* 
     FROM posts p 
LEFT JOIN users u ON p.user_id = u.id 
    WHERE p.type IN ('post', 'page', 'file') 
 GROUP BY p.user_id 
 ORDER BY p.created_at DESC 
    LIMIT 30

Но это слишком медленно, даже ограничено 30 записями.

Теперь, как я могу ускорить этот запрос?какие столбцы индексировать или какие-либо другие идеи?спасибо.

Ответы [ 4 ]

2 голосов
/ 08 марта 2011

Первое, что нужно сделать, это добавить индекс на posts.user_id (или, может быть, posts.user_id + posts.type). И еще один индекс на posts.created_at

UPDATE
Я только что обратил внимание, что ваш запрос захватывает все поля из обеих таблиц, а в таблице сообщений есть 6 длинных текстовых столбцов. Поэтому я считаю, что у вас низкая производительность, потому что mysql должен создать довольно большую временную таблицу или временный файл, чтобы получить все строки для удовлетворения ваших group by + order by предложений. Я думаю, что следующий запрос должен помочь.

  SELECT u.*, p1.* FROM
  users u 
  INNER JOIN 
  (
      SELECT p.user_id, p.created_at, p.id FROM posts p 
      WHERE  p.type IN ('post', 'page', 'file')  GROUP by p.user_id 
      ORDER BY p.created_at DESC LIMIT 30
  )xxx ON xxx.user_id = u.id
   INNER JOIN posts p1 ON (p1.id = xxx.id)
0 голосов
/ 08 марта 2011

Попробуйте ответ @ Габриэля, но с ПРЕДЕЛОМ во внутреннем запросе.

ВЫБРАТЬ стр. , u. ОТ (ВЫБРАТЬ * ИЗ ПОЛОЖЕНИЙ, ГДЕ вводите IN ('post', 'page ',' file ') ORDER BY create_at DESC LIMIT 30) p ВЛЕВО ПРИСОЕДИНЯЙТЕСЬ к пользователям u ВКЛ p.user_id = u.id ORDER BY p.created_at;

0 голосов
/ 08 марта 2011

Вы можете попробовать это:

ВЫБРАТЬ p. , u.
ОТ (ВЫБРАТЬ * ИЗ ПОЛОЖЕНИЙ, ГДЕ p.type IN ('post', 'page', 'file ')) p
LEFT JOIN пользователи u ON p.user_id = u.id
GROUP BY p.user_id ORDER BY p.created_at DESC LIMIT 30

MySQL сначала выполняет внутренний запросс его результатом обработайте внешний запрос с меньшим количеством записей.

0 голосов
/ 08 марта 2011

Что касается индексов, я бы предложил создать их для posts.type (WHERE), posts.created_at (ORDER). Это должно помочь ускорить сортировку.

...