Oracle / SQL - нужна помощь в оптимизации запроса объединения / группы / количества - PullRequest
1 голос
/ 26 января 2011

Я пытаюсь оптимизировать этот запрос, насколько это возможно. В моих тестовых таблицах это делает именно то, что мне нужно, но на живых таблицах это занимает ОЧЕНЬ много времени для запуска.

select   THING_, 
            count(case STATUS_ when '_Good_' then 1 end) as GOOD, 
            count(case STATUS_ when '_Bad_' then 1 end) as BAD,
            count(case STATUS_ when '_Bad_' then 1 end) / count(case STATUS_ when '_Good_' then 1 end) * 100 as FAIL_PERCENT
    from    
                (
                select      THING_,
                            STATUS_,
                    from    <good table>
                    where   TIMESTAMP_ > (sysdate - 1) and
                            STATUS_ = '_Good_' and
                            upper(THING_) like '%TEST%'

                UNION ALL           

                select      THING_,
                            STATUS_,
                    from    <bad table>
                    where   TIMESTAMP_ > (sysdate - 1) and
                            STATUS_ = '_Bad_' and
                            THING_THING_ like '%TEST%'
                ) u
    group by THING_ 

Я думаю, что, посмотрев на запрос, он должен пояснить, что я хочу сделать, но если нет или если потребуется дополнительная информация, пожалуйста, дайте мне знать, и я опубликую несколько примеров таблиц.

Спасибо!

Ответы [ 3 ]

2 голосов
/ 26 января 2011

Создание составных индексов (STATUS_, TIMESTAMP_) в обеих таблицах.

0 голосов
/ 26 января 2011

(1) Анализ плана выполнения всегда должен быть вашим первым шагом в диагностике проблем производительности SQL

(2) Возможная проблема с написанным запросом заключается в том, что SYSDATE - это функция, которая не являетсяПри оценке до времени выполнения (т. е. после определения плана выполнения) оптимизатор не может использовать гистограммы в столбце метки времени для оценки полезности индекса.Я видел, что приводит к плохим решениям оптимизатора.Если вы можете сначала найти способ вычисления даты, а затем ввести ее в запрос в виде привязки или литерала, это может помочь, хотя на самом деле это всего лишь предположение.

(3) Может быть, лучше в целомспособ структурирования запроса - объединение (возможно полное внешнее объединение) между агрегатными запросами в каждой из таблиц.

SELECT COALESCE(g.thing_,b.thing_), COALESCE(good_count,0), COALESCE(bad_count,0)
  FROM (SELECT thing_,count(*) good_count from good_table WHERE ... GROUP BY thing_) g
       FULL OUTER JOIN
       (SELECT thing_,count(*) bad_count from bad_table WHERE ... GROUP BY thing_) b
       ON b.thing_ = g.thing_

(Должен сказать, что странно, что у вас есть две отдельные таблицыкогда у вас также есть столбец состояния, чтобы указать «хорошо» или «плохо». Но, возможно, я переоцениваю.)

0 голосов
/ 26 января 2011

Вы пробовали использовать аналитическую функцию? Это может уменьшить время выполнения. Вот вам пример:

select distinct col1, col2, col3
(Select col1,
       count(col2) over (partition by col1) col2,
       count(col3) over (partition by col1) col3
from table
)

Это что-то вроде этого.

...