Slow Query - Помощь с оптимизацией - PullRequest
1 голос
/ 05 июня 2009

Привет, ребята. Это продолжение этого вопроса :

После получения нужных данных и внесения некоторых изменений, основанных на запросах бизнеса, у меня теперь есть этот мини-зверь. Этот запрос должен вернуть общее количество новых регистраций соискателей и количество новых загруженных резюме:

SELECT COUNT(j.jobseeker_id) as new_registrations,
(
    SELECT 
      COUNT(c.cv_id)
    FROM 
      tb_cv as c, tb_jobseeker, tb_industry
    WHERE
      UNIX_TIMESTAMP(c.created_at) >= '1241125200'
    AND 
      UNIX_TIMESTAMP(c.created_at) <= '1243717200'
    AND 
      tb_jobseeker.industry_id = tb_industry.industry_id
) 
AS uploaded_cvs
FROM 
  tb_jobseeker as j, tb_industry as i
WHERE
  j.created_at BETWEEN '2009-05-01' AND '2009-05-31'
AND
  i.industry_id = j.industry_id
GROUP BY i.description, MONTH(j.created_at) 

Примечания: - Два значения в функциях UNIX TIMESTAMP передаются в качестве параметров из модуля отчета в нашем бэкэнде.

Каждый раз, когда я запускаю его, MySQL задыхается и молча задерживается в эфире сети.

Помощь приветствуется.

Обновление: Эй, ребята. Большое спасибо за все вдумчивые и полезные комментарии. Я только 2 недели в моей роли здесь, поэтому я все еще изучаю схему. Таким образом, этот запрос находится где-то между чертовски и образованным предположением. Начну отвечать на все ваши вопросы сейчас.

Ответы [ 2 ]

6 голосов
/ 05 июня 2009

tb_cv не связан с другими таблицами в подзапросе. Я думаю, что это коренная причина медленного запроса. Это приводит к генерации декартового произведения, в результате чего получается гораздо больше строк, чем вам, вероятно, нужно.

Кроме того, я бы сказал, что вам нужны индексы для tb_jobseeker.created_at, tb_cv.created_at и tb_industry.industry_id, и вы можете захотеть избавиться от вызовов UNIX_TIMESTAMP() в подзапросе, поскольку они препятствуют использованию индекс. Вместо этого используйте BETWEEN и фактические значения поля.

Вот моя попытка понять ваш запрос и написать лучшую версию. Я полагаю, вы хотите получить количество новых регистраций соискателей и новых загруженных резюме в месяц для каждой отрасли:

SELECT 
  i.industry_id,
  i.description, 
  MONTH(j.created_at)            AS month_created,
  YEAR(j.created_at)             AS year_created,
  COUNT(DISTINCT j.jobseeker_id) AS new_registrations,
  COUNT(cv.cv_id)                AS uploaded_cvs
FROM 
  tb_cv AS cv
  INNER JOIN tb_jobseeker AS j ON j.jobseeker_id = cv.jobseeker_id
  INNER JOIN tb_industry  AS i ON i.industry_id  = j.industry_id
WHERE
  j.created_at BETWEEN '2009-05-01' AND '2009-05-31'
  AND cv.created_at BETWEEN '2009-05-01' AND '2009-05-31'
GROUP BY 
  i.industry_id,
  i.description, 
  MONTH(j.created_at),
  YEAR(j.created_at)

Несколько вещей, которые я заметил при написании запроса:

  • значения GROUP BY, которые вы не выводите в конце. Зачем? ( Я добавил сгруппированное поле в список вывода. )
  • вы присоединяетесь к трем таблицам в подзапросе, используя только значения из одной из них. Зачем? Я не понимаю, для чего это было бы полезно, кроме как отфильтровывать записи CV, в которых нет соискателей или представителей отрасли & mdash; что мне трудно представить. ( Я удалил весь подзапрос и вместо него использовал простой COUNT. )
  • Ваш подзапрос каждый раз возвращает одно и то же значение. Возможно, вы хотели как-то соотнести это с отраслью?
  • Подзапрос выполняется один раз для каждой записи в сгруппированном запросе, без включения в статистическую функцию.
0 голосов
/ 05 июня 2009

Прежде всего, возможно, стоит перенести преобразования 'UNIX_TIMESTAMP' на другую сторону уравнения (то есть выполнить обратную функцию для буквенных значений меток времени на другой стороне> = и <=). Это избавит внутренний запрос от необходимости выполнять преобразования для каждой записи, а не один раз для запроса. </p>

Кроме того, почему в запросе uploaded_cvs нет предложения where, связывающего его с внешним запросом? Я что-то здесь упускаю?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...