Нужна помощь с оптимизацией запроса SQL - PullRequest
0 голосов
/ 28 июня 2011

Мне очень нужна помощь с запросом, который в последние 6 месяцев вызывал много горя на сайте с высоким трафиком.Я являюсь разработчиком веб-интерфейса и могу писать простые запросы SQL, поэтому не могу самостоятельно решить эту проблему.Запрос теперь часто блокирует базу данных mysql из-за нехватки памяти или процессора или помех от других запросов на VPS.Я модернизировал оборудование, но это само по себе не решило проблему.Итак, вот описание того, что пытается сделать запрос:

Пользователь обращается к определенному URL (скажем, the_source_url).Приложение пытается извлечь связанные source_urls, к которым ранее обращались другие пользователи (которые также обращались к the_source_url), отсортированные по наиболее часто используемым и наименее часто используемым.По сути, приложение пытается найти пользователей со схожим интересом и показать другие страницы, к которым они обращались ранее.

Это «сложный запрос», который я написал, когда был молод / глуп, и на сайте не было трафика:

SELECT DISTINCT(SOURCE_URL), COUNT(SOURCE_URL) CATCOUNT 
  FROM topsources 
 WHERE SOURCE_URL <> ? 
   AND USER_ID IN (SELECT DISTINCT(USER_ID) 
                     FROM topsources WHERE SOURCE_URL = ?) 
GROUP BY SOURCE_URL ORDER BY CATCOUNT DESC

Это структура таблицы:

`topsources` (
  `USER_ID` varchar(255) NOT NULL,
  `DATE_AND_HOUR` varchar(255) NOT NULL,
  `UPDATED_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `ITEM_ID` int(11) NOT NULL,
  `SOURCE_URL` varchar(100) NOT NULL,
  `FEED_PAGE_URL` varchar(255) NOT NULL,
  `CATEGORY_URL` varchar(100) NOT NULL,
  `REFERRER` varchar(2048) DEFAULT NULL,
  PRIMARY KEY (`USER_ID`,`DATE_AND_HOUR`(30),`ITEM_ID`),
  KEY `USER_ID` (`USER_ID`),
  KEY `FEED_PAGE_URL` (`FEED_PAGE_URL`),
  KEY `SOURCE_URL` (`SOURCE_URL`),
  KEY `CATEGORY_URL` (`CATEGORY_URL`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Обратите внимание, что я уже пытался выполнить внутреннее объединение вместо выбора, но это не работает.т. е. приведенный ниже запрос не возвращает тот же результат, что и запрос выше.

SELECT DISTINCT(ts.SOURCE_URL), COUNT(ts.SOURCE_URL) CATCOUNT FROM topsources ts INNER JOIN topsources tsi ON ts.USER_ID = tsi.USER_ID AND tsi.SOURCE_URL = ? WHERE ts.SOURCE_URL <> ? AND ts.CATEGORY_URL = ? GROUP BY ts.SOURCE_URL ORDER BY ts.CATCOUNT DESC

Ответы [ 2 ]

4 голосов
/ 28 июня 2011

IN подвыборы не оптимизированы в MySQL. Вместо того, чтобы выполнять отбор, а затем отбор, MySQL выполняет отбор для каждой строки, соответствующей внешнему выбору. По этой причине подвыборы в предложении IN должны быть заменены соединениями. Вот более быстрая версия запроса:

SELECT DISTINCT(SOURCE_URL), COUNT(SOURCE_URL) CATCOUNT 
FROM topsources 
INNER JOIN 
(SELECT DISTINCT(USER_ID) 
                 FROM topsources WHERE SOURCE_URL = ?) as t
ON (topsources.USER_ID = t.USER_ID)
WHERE SOURCE_URL <> ? 
GROUP BY SOURCE_URL ORDER BY CATCOUNT DESC
1 голос
/ 28 июня 2011

Это требует нормализации. Что вам действительно нужно, так это URL-таблица типа

id | url
1  | http://....

Тогда в вашей таблице верхних источников

id | url_id
1  | 1

Тогда ваш DISTINCT (url_id) должен быть значительно быстрее.

...