2015-07-16 2 views
0

У меня есть sql using Oracle SQL Developer ниже, который работает, но меня беспокоит производительность над большей живой базой данных.Оптимизация SQL-запроса в where where

Извините за все таблицы соединений, это показывает соединения с таблицей _aud и ревизионной таблицей, которая хранит историю аудита.

select cust.forename, cust.surname 
from customer cust 
join section_details sd on cust.section = sd.section 
where 
-- this value is substituted programatically 
sd.type = 5 and 
(
    (select max(rt.timestamp) 
    from 
    customer cust_tmp1 
    join section_details sd on cust_tmp1.section = sd.section 
    join measure msr on sd.measure = msr.id 
    join measure_aud msr_a on msr.id = msr_a.id 
    join revision_table rt on msr_a.rev = rt.id 
    where 
    cust_tmp1.id = cust.id and msr.measure = 'Last Contact Date') 
> 
    (select max(rt.timestamp) 
    from 
    customer cust_tmp2 
    join section_details sd on cust_tmp2.section = sd.section 
    join measure msr on sd.measure = msr.id 
    join measure_aud msr_a on msr.id = msr_a.id 
    join revision_table rt on msr_a.rev = rt.id 
    where 
    cust_tmp2.id = cust.id and msr.measure = 'Last Order Date') 
); 

Короче говоря, я только хочу, чтобы получить сведения о клиенте, если «последний контакт Date» более поздняя, ​​чем «дату последнего заказа». Я заканчиваю тем, что максимальная отметка (временная метка) из одного выбора больше, чем максимальная (временная метка) из другого выбора.

Все работает отлично, и я получаю ожидаемые результаты.

Каждая сторона сравнения временной метки дублируется отдельно от msr.measure = 'Last Contact Date' или 'Last Order Date'.

Я пробовал несколько альтернатив, которые никогда не работали, поскольку они приводили к многоуровневым вложенным подзапросам, и я не мог пройти во внешней записи cust.

Любые дальнейшие идеи были бы весьма признательны.

+0

Пожалуйста, отметьте свой вопрос в базе данных, которую вы используете. –

+0

Я пометил oracle11g и обновил свой вопрос. Спасибо за ответы, я попробую их обоих в ближайшее время, если я смогу или первым делом завтра и обновить здесь. –

ответ

-1

Я попытался решение опубликовано здесь, и все они, кажется, работают , большое спасибо за ответы - я раньше не исследовал предложение о наличии.

Я добавил необходимые индексы и выполнил планы объяснений по всем параметрам, мой первоначальный запрос имел самую низкую стоимость. Поэтому я думаю, что буду использовать этот вариант, продвигаясь вперед.

0

Вы можете переключить это на exists:

exists (select max(rt.timestamp) 
     from customer cust_tmp1 join 
      section_details sd 
      on cust_tmp1.section = sd.section join 
      measure msr 
      on sd.measure = msr.id join 
      measure_aud msr_a 
      on msr.id = msr_a.id join 
      revision_table rt 
      on msr_a.rev = rt.id 
     where cust_tmp1.id = cust.id and 
       msr.measure in ('Last Contact Date', 'Last Order Date') 
     having max(case when msr.measure = 'Last Contact Date' then rt.timestamp end) > 
       max(case when msr.mesure = 'Last Order Date' then rt.timestamp end) 
     ); 

Я не уверен, если будет большой выигрыш в производительности. Если у вас есть нужные индексы в вашей базе данных, ваша оригинальная версия должна быть довольно быстрой и масштабируемой.

1

Вы уверены, что вам нужны все эти объединения?

тот же запрос с различным WHERE-условиях, как правило, приводит к ДЕЛУ:

select cust.forename, cust.surname 
from customer cust 
where 
    -- this value is substituted programatically 
    sd.type = 5 
and exists 
(select * 
    from 
    customer cust_tmp1 
    join section_details sd on cust_tmp1.section = sd.section 
    join measure msr on sd.measure = msr.id 
    join measure_aud msr_a on msr.id = msr_a.id 
    join revision_table rt on msr_a.rev = rt.id 
    where cust_tmp1.id = cust.id 

    having max(case when msr.measure = 'Last Contact Date' then rt.timestamp end) 
     > max(case when msr.measure = 'Last Order Date' then rt.timestamp end) 
) 

или упрощено удаление подзапросы:

select cust.forename, cust.surname 
from customer cust 
join section_details sd on cust_tmp1.section = sd.section 
join measure msr on sd.measure = msr.id 
join measure_aud msr_a on msr.id = msr_a.id 
join revision_table rt on msr_a.rev = rt.id 
where 
    -- this value is substituted programatically 
    sd.type = 5 
group by cust.forename, cust.surname 
having max(case when msr.measure = 'Last Contact Date' then rt.timestamp end) 
    > max(case when msr.measure = 'Last Order Date' then rt.timestamp end)