2013-04-29 2 views
0

У меня есть следующий запрос, но он медленно запускается в моем sql editor! Как улучшить его (написать мудрый), чтобы ускорить выполнение запроса.Как повысить производительность вложенного запроса?


SELECT year,main_code,name,father_code,main_code || '__' || year AS main_id, 
(SELECT COUNT(*) FROM GK_main 
WHERE father_code=sc.main_code AND 
year= (SELECT MAX(year)FROM SS_job)) childcount 
FROM GK_main sc WHERE year=(SELECT MAX(year)FROM SS_job) 
+0

Поскольку 'SELECT max (year) из SS_job' является статическим, сначала попробуйте сначала его перенести в локальную переменную, а затем просто обратитесь к ней. В противном случае вы выполняете 'SELECT max (год) из SS_job' дважды для каждой строки в GK_main – DeanOC

+0

Не могли бы вы написать запрос, пожалуйста, –

+1

, следуя логике DeanOC, вы можете поместить этот select ss_job в основное предложение FROM:' FROM gk_main sc, (выберите max (год) из ss_job), поскольку ss_job (year) ', будет иметь тот же эффект, используя внешнюю переменную, где этот макс будет выполняться только один раз. – ceinmart

ответ

1

Эффективность зависит больше от доступных индексов, а не так, как это написано. Вы можете попробовать эту версию (без встроенных подзапросов):

SELECT 
    sc.year, 
    sc.main_code, 
    sc.name, 
    sc.father_code, 
    sc.main_code || '__' || sc.year AS main_id, 
    NVL(g.childcount, 0) AS childcount 
FROM 
    GK_main sc 
    LEFT JOIN 
    (SELECT father_code , 
      COUNT(*) AS childcount 
     FROM GK_main 
     WHERE year = (SELECT MAX(year) FROM SS_job) 
     GROUP BY father_code 
    ) AS g 
     ON g.father_code = sc.main_code 
WHERE 
    sc.year = (SELECT MAX(year) FROM SS_job) ; 

Но что принесет пользу эффективности бы индексов.

  • Есть ли индекс на SS_job (year)?
  • Есть ли индекс на GK_main (year, father_code) или на GK_main (father_code, year)?
  • Есть ли индекс на GK_main (year, main_code) или на GK_main (main_code)?
+0

Отлично, но некоторые записи 'childcount' пустая строка, а не' 0' !! –

+1

Да, исправлено. –

+0

'COALESCE (g.childcount, 0)' НЕ МОЖЕТ БЫТЬ РЕШЕНО informix. –

1

Используйте объединение вместо подзапроса.

SELECT sc.year,sc.main_code,sc.name,sc.father_code,sc.main_code || '__' || sc.year AS main_id, 
COUNT(F.father_code) AS childcount 
FROM GK_main sc LEFT JOIN GK_main F ON F.father_code = sc.main_code 
WHERE year=(SELECT MAX(year)FROM SS_job) 
GROUP BY sc.year,sc.main_code,sc.name,sc.father_code 

Не проверено и сделано быстро, поэтому может содержать ошибку. Но это должно по крайней мере избавить вас от проверки SELECT MAX (год) FROM SS_job дважды.

Я бы никогда не делал COUNT (*), но всегда выбирал столбцы, которые я хочу сосчитать.

+2

Почему вы считаете, что 'COUNT (*)' менее эффективен, чем 'COUNT (column)'? –

+0

@ypercude Я бы посмотрел: http://stackoverflow.com/questions/2219843/count-vs-countid-in-sql-server-2005. Это объясняет это лучше, чем я могу. Это больше связано с замками, чем с производительностью. –

+0

Ответ на совершенно другую дорогу, используя системные представления. –

1

Попробуйте этот запрос

SELECT 
    year, 
    main_code, 
    name, 
    father_code, 
    main_code || '__' || year AS main_id, 
    childcount.cnt as 'count' 
FROM 
    GK_main sc 
LEFT JOIN 
    (SELECT 
     father_code, 
     COUNT(*) AS cnt 
    FROM 
     GK_main 
    WHERE 
     year= (SELECT MAX(year)FROM SS_job) 
    GROUP BY 
     father_code) childcount 
ON childcount.father_code = sc.main_code 

Создать necesary индекс (father_code, year), который поможет

+0

Неверные данные. мой предыдущий запрос получает запись 1067, с другой стороны, ваш запрос получает только запись '640' !! –

+0

Проверьте правильность .. – Meherzad

+0

'5747' вместо' 1067' !! и счетчик не правильный –