Присоединение к одной таблице строк занимает слишком много времени

Я пытаюсь прочитать все коды продуктов (столбцы mal_no) и количественные данные (столбцы adet) из таблицы (которая является таблицей "hso" и проиндексирована с помощью mal_no, все таблицы ниже имеют индексы для mal_no), но даже если она имеет только 1 ряд данных он продолжает работать и никогда не заканчивается.

Запрос без этого объединения (путем добавления только закомментированной части ниже) является немедленным.

У вас есть предложения по этому поводу?

Спасибо,

select mt.mal_no,hso.adet siparis,
  mot.birim_no,round((mbs.eldeki_stok_miktar*0.8),0) duzelts,
  mot.oncelik,
  SUM(round((mbs.eldeki_stok_miktar*0.8),0)) OVER(ORDER BY 
    mot.oncelik desc ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) kumule_stok
from mal_birim_ambar_detay@live mbs
  ,mal_tanim@live mt
  ,mss_temin_yeri_oncelik@live mot
  ,web_hso hso
where 1=1
and hso.mal_no=mbs.mal_no
and mbs.mal_no=mt.mal_no
and mbs.birim_no=mot.birim_no
and mt.mal_grup_no=mot.mal_grup_no
and mt.mal_altgrup_no=mot.mal_altgrup_no
--and mt.mal_no in ('1035541001') 
and mbs.eldeki_stok_miktar>0
and mot.oncelik>0
and mbs.ambar_no='01'
order by mot.oncelik desc

2 ответа

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

Локальная база данных отправит подзапросы к удаленной базе данных; но объединение и фильтрация происходят локально, поэтому существует вероятность передачи большого количества избыточных данных из удаленной базы данных. Поэтому вам нужно предоставить оптимизатору достаточно информации, чтобы он мог создавать умные подзапросы.

Например, изолируйте удаленные таблицы во встроенном представлении:

select rmt.mal_no,
      hso.adet siparis,
      rmt.birim_no,
      rmt.duzelts,
      rmt.oncelik,
      rmt.kumule_stok
from web_hso hso
     join 
      ( select mt.mal_no,
              mot.birim_no,
              round((mbs.eldeki_stok_miktar*0.8),0) duzelts,
              mot.oncelik,
              SUM(round((mbs.eldeki_stok_miktar*0.8),0)) 
                OVER(ORDER BY mot.oncelik desc ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) kumule_stok
from mal_birim_ambar_detay@live mbs
     join mal_tanim@live mt
       on mbs.mal_no=mt.mal_no
     join mss_temin_yeri_oncelik@live mot
      on mbs.birim_no=mot.birim_no
      and mt.mal_grup_no=mot.mal_grup_no
      and mt.mal_altgrup_no=mot.mal_altgrup_no
      where mbs.eldeki_stok_miktar>0
      and mot.oncelik>0
      and mbs.ambar_no='01' ) rmt
    on hso.mal_no=rmt.mal_no
    order by rmt.oncelik desc

Очевидно, это только предположение, потому что я не понимаю вашу модель данных или ваши данные. Вам нужно применить свои знания предметной области здесь, чтобы составить хороший запрос. Одни только встроенные представления не могут обеспечить всю необходимую вам скорость. Например, если большая часть работы включает в себя объединения трех удаленных таблиц, и, скорее всего, это так, то, как предполагает @BriteSponge, вы можете найти, используя driving_site подсказка может значительно улучшить производительность. Таким образом, используя встроенный вид сверху, код будет начинаться

select  /*+DRIVING_SITE(rmt)*/ 
      rmt.mal_no,
      hso.adet siparis,
      rmt.birim_no,
      rmt.duzelts,
      rmt.oncelik,
      rmt.kumule_stok
from web_hso hso
     join ( ... ) rmt
     on hso.mal_no=rmt.mal_no

Документ Oracle имеет дальнейшие указания. Узнайте больше

Трудно сказать по этой большой информации.

Но я бы предложил вам выполнить следующие действия:

  1. Если у вас есть администратор базы данных или у вас есть соответствующий инструмент, проверьте план выполнения. (Например, TOAD показывает план выполнения для баз данных Oracle.)
  2. Если вы видите "полное сканирование" в плане выполнения внутри вложенных циклов, это означает, что база данных сканирует таблицу снова и снова.

Для общего подхода вы можете использовать эти методы:

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

И, наконец, по принципу старайтесь избегать больших объединений. Раздели и покори свои данные. Попробуйте написать вложенные циклы и использовать столько же, сколько индексы при получении ваших данных.

Другие вопросы по тегам