如下查询:
a,b表做过同义词 ,都是通过dblink查询的 sql1 : select a.name b.*
  from a, b
 where a.id = b.id
 where b.mtime < to_date('20050501', 'yyyy-mm-dd')
 group by a.name 
 --0.1s内出结果
sql2:select *
  from (select a.name b.*
          from a, b
         where a.id = b.id
         where b.mtime < to_date('20050501', 'yyyy-mm-dd')
         group by a.name)
-- 出不来结果 (不是慢,a表300w,b表900w)
一开始不了解,弄了很久,发现是dblink 影响了执行计划,
针对sql2 查询慢的解决办法如下(hint):select *
  from (select /*+ driving_site(a) +driving_site(b)*/ a.name b.*
          from a, b
         where a.id = b.id
         where b.mtime < to_date('20050501', 'yyyy-mm-dd')
         group by a.name)
加上 driving_site 强制与ORACLE所选择的位置不同的表进行查询执行. 好了速度起来了 执行计划中也可以看到 走了 a,b表的索引!
但是新的问题出现了,我需要利用 sql2的查询结果做一个连接查询:select * from(
select *
  from (select /*+ driving_site(a) +driving_site(b)*/ a.name b.*
          from a, b
         where a.id = b.id
         where b.mtime < to_date('20050501', 'yyyy-mm-dd')
         group by a.name)) t_main left join t_task
         on t_task.name=t_main.nameps:t_task是两个本地表联合查询出来的结果,0.05s内出结果, 这里整个sql的执行计划 仿佛回到了 sql1,为 filter ,remote   ,当去掉 left join 后面一截时 整个查询、执行计划 正常 ,速度很快,求解,谢谢 !!

解决方案 »

  1.   

    将select a.name b.*
      from a, b
     where a.id = b.id
     where b.mtime < to_date('20050501', 'yyyy-mm-dd')
     group by a.name 
    结果存入临时表,然后进行处理吧,DBLINK;影响性能比较难处理
      

  2.   

    select a.name b.*
      from a, b
     where a.id = b.id
     where to_char(b.mtime,'yyyymmdd') < '20050501'
     group by a.name  你这样执行看看,理论上连接DBLINK影响是有,但不会很大,尽量缩小语法查询范围,比较查询结果看看,或依2楼所言建立临时表处理
      

  3.   

     二楼这样做见笑了, to_char(b.mtime,'yyyymmdd')  b表数据 900w 差不多1千万了,还有mtime的索引,to_char一个全表扫描,索引失效!整个就出不来数据了。
      

  4.   

    1、当指定 /*+ driving_site(a) +driving_site(b)*/ 时, oracle将会从本地库表获取全部数据到dblink数据库来进行关联运算.(索引会起作用,速度快)
    若指定 /*+driving_site(t_task)*/ 时, oracle将会从dblink库中的a、b表获取全部数据到t_task表所在的数据库来进行关联运算.(索引会失败,全表扫描)2、DRIVING_SITE作用和ORDERED类似。DRIVING_SITE通常在分布式查询中使用。如果没有这个提示,Oracle会先从远程点检索,并将它们连接到本地站点中。通过使用DRIVING_SITE,我们可以先在本地进行检索,将检索后的数据发送到远程节点进行连接。
      

  5.   

    select * from(
    select /*+ driving_site(t_main) */ *  from (select a.name b.*
              from a, b
             where a.id = b.id
             where b.mtime < to_date('20050501', 'yyyy-mm-dd')
             group by a.name)) t_main left join t_task
             on t_task.name=t_main.name
    试试这样行不行!