Присоединение к одной таблице строк занимает слишком много времени
Я пытаюсь прочитать все коды продуктов (столбцы 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 имеет дальнейшие указания. Узнайте больше
Трудно сказать по этой большой информации.
Но я бы предложил вам выполнить следующие действия:
- Если у вас есть администратор базы данных или у вас есть соответствующий инструмент, проверьте план выполнения. (Например, TOAD показывает план выполнения для баз данных Oracle.)
- Если вы видите "полное сканирование" в плане выполнения внутри вложенных циклов, это означает, что база данных сканирует таблицу снова и снова.
Для общего подхода вы можете использовать эти методы:
- Среди условий условия находят те, которые уменьшают множество в первую очередь.
- (Oracle) используют подсказки индекса и подсказку use_nl, чтобы явно определить базу данных, как она должна идти к таблицам.
И, наконец, по принципу старайтесь избегать больших объединений. Раздели и покори свои данные. Попробуйте написать вложенные циклы и использовать столько же, сколько индексы при получении ваших данных.