Почему этот SELECT занимает 2-3 минуты и как я могу уменьшить его до нескольких секунд? - PullRequest
0 голосов
/ 30 декабря 2011
select to_date(checks.payment_dte, 'YYYYMMDD') as payment_date,
       checks.run_number, 
       checks.check_nbr as check_number, 
       checks.check_amt as check_amount, 
       checks.payee_no as payee_number, 
       checks.loc as location, 
       checks.fac_state as facility_state, 
       checks.delta_usa_ind, 
       checks.payee_lnme as payee_last_name, 
       checks.payee_fnme as payee_first_name, 
       checks.payee_addr1 as payee_address1, 
       checks.payee_addr2 as payee_address2, 
       checks.payee_addr3 as payee_address3, 
       checks.payee_city, 
       checks.payee_st as payee_state, 
       to_char(checks.payee_zip, '00000') as payee_zip,
       to_char(checks.payee_zip4, '0000') as payee_zip4, 
       checks.payee_country_cde as payee_country_code,
       country.country_abbreviation as payee_country_code_description, 
       checks.maint_code as maintenance_code, 
       checks.mod_dte as mod_date, 
       checks.mod_op, 
       checks.payment_profile_id, 
       checks.bank_profile_id, 
       checks.parent_id
from (select c.*, 
             check_total
      from db1.tbl_payment_checks c
      join (select sum(net) as check_total, 
                   check_nbr
            from (select nvl(sum(total_net),0) net, 
                         check_nbr
                  from db1.tbl_wip_hist_header
                  group by check_nbr
                  union all
                  select nvl(sum(refund_amount)*-1,0) net, 
                         check_number check_nbr
                  from db1.tbl_payment_refund_header
                  group by check_number)
            group by check_nbr) sums on (c.check_nbr = sums.check_nbr)
      where payee_no = '840932794'
      order by payment_dte desc) checks
left join db1.tbl_code_country country
             on (checks.payee_country_cde = country.country)
where rownum < 10
order by payment_dte desc

Ответы [ 4 ]

5 голосов
/ 30 декабря 2011

Выйти со всеми групповыми байтами и подзапросами. Вы можете просто использовать left join s и предложение over, чтобы получить то, что вы хотите:

select to_date(checks.payment_dte, 'YYYYMMDD') as payment_date,
       checks.run_number, 
       checks.check_nbr as check_number, 
       checks.check_amt as check_amount, 
       checks.payee_no as payee_number, 
       checks.loc as location, 
       checks.fac_state as facility_state, 
       checks.delta_usa_ind, 
       checks.payee_lnme as payee_last_name, 
       checks.payee_fnme as payee_first_name, 
       checks.payee_addr1 as payee_address1, 
       checks.payee_addr2 as payee_address2, 
       checks.payee_addr3 as payee_address3, 
       checks.payee_city, 
       checks.payee_st as payee_state, 
       to_char(checks.payee_zip, '00000') as payee_zip,
       to_char(checks.payee_zip4, '0000') as payee_zip4, 
       checks.payee_country_cde as payee_country_code,
       country.country_abbreviation as payee_country_code_description, 
       checks.maint_code as maintenance_code, 
       checks.mod_dte as mod_date, 
       checks.mod_op, 
       checks.payment_profile_id, 
       checks.bank_profile_id, 
       checks.parent_id,
       sum(nvl(h.total_net, 0) + nvl(r.refund_amount,0)*-1) over (partition by checks.check_nbr) as check_total
from 
    db1.tbl_payment_checks checks
    left join db1.tbl_wip_hist_header h on
        checks.check_nbr = h.check_nbr
    left join db1.tbl_payment_refund_header r on
        checks.check_nbr = r.check_nbr
    left join db1.tbl_code_country country on 
        checks.payee_country_cde = country.country
where 
    rownum < 10
    and checks.payee_no = '840932794'
order by payment_dte desc

Это должно работать намного быстрее.

1 голос
/ 30 декабря 2011

Ваш запрос медленный, потому что он сложный. ВЫ ВЫБИРАЕТЕ из SELECT, который присоединяется к SELECT-UNION-SELECT. Это много данных, которые нужно поместить в память и запрашивать снова и снова. Я думаю, что вам нужно подумать о реорганизации этого запроса с нуля.

0 голосов
/ 30 декабря 2011

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

  1. Заменить все вложенные подзапросы переменными таблицы и выполнить объединение с переменными таблицы.,Вставьте возвращаемые данные вложенных запросов в переменные таблицы и используйте их в основном запросе.Это повысит удобочитаемость вашего запроса, и вы сможете найти сегрегированную область улучшений в запросе.

  2. Создайте первичный ключ для табличных переменных, если это возможно по характеру столбца, он создасткластеризованный индекс для табличной переменной, и ваши объединения будут выполняться быстрее.

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

0 голосов
/ 30 декабря 2011

Я бы попытался вытащить объединение, в котором вы получаете check_total, в строку выбора.
Я подозреваю, что оно выполняет объединение для всех строк и применяет where, где payee_no =.
Если оно вытянуто ввыберите, тогда план запроса может стать умнее.
Это всего лишь пример использования запроса в строке выбора.

   select top sID, sParID, (select COUNT(*) from docSVsys as C where c.sParID = docSVsys.sParID) as famSize
   from docSVsys

С реальным предложением where, когда я выполнял famSize с объединением и группой.иногда я получал низкую производительность, так как он вычислял famSize для всей таблицы, но где возвращалось только 10 строк.С другой стороны, если запрос возвратил более 1/4 строк в docSVsys, тогда соединение было лучше.

Я на MSSQL.Если это не поддерживается в Oracle, извините.

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