加入1行表需要花费太多时间

时间:2017-07-20 07:26:04

标签: sql oracle performance query-optimization distributed-database

我正在尝试从表中读取所有产品代码(mal_no列)和数量数据(adet列)(" hso"表并由mal_no索引,下面的所有表都包含mal_no的索引)即使它只有一行数据,它仍然在运行,永远不会结束。

没有此连接的查询(通过仅添加下面注释掉的部分)是立即的。

你有什么建议吗?

谢谢,

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 个答案:

答案 0 :(得分: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建议您可能发现使用the driving_site hint可以显着提高性能。因此,使用上面的内联视图,代码将启动

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文档有进一步的指导。 Find out more

答案 1 :(得分:0)

很难从这些信息中分辨出来。

但我建议你按照以下步骤操作:

  1. 如果您有任何数据库管理员或者您有合适的工具,请检查执行计划。 (例如,TOAD显示了Oracle数据库的执行计划。)
  2. 如果您看到"完整扫描"在嵌套循环中的执行计划中,这意味着数据库一遍又一遍地扫描表。
  3. 对于整体方法,您可以使用以下方法:

    1. 其中条件项目中找到首先减少集合的项目。
    2. (Oracle)使用索引提示和use_nl提示来显式定义数据库,它应该如何转到表中。
    3. 最后,为了一个原则,尽量避免大联合。划分并征服您的数据。尝试编写嵌套循环,并在检索数据时使用索引。