使用DBLINK远程访问数据库的优化策略和思路:
策略:远程访问,网络传输占很大部分,优化原则,减少网络传输,将小的结果集拉到本地处理;
思路1:在远端建立视图;
思路2:使用DRIVING_SITE将数据拉到本地处理;
出现这种执行计划,主要原因是使用了db link,要想看到执行计划,可以加 hint,如:
/*+remote_mapping(db_link)*/或/*+driving_site(table_name)*/
用法: /*+driving_site(table_name)*/ : table_name 一般是大表!
在近期的一个数据库查询统计中,需要通过db_link跨库进行表的关联,其中A库 中的某张拥有百万以上数据的表与B库 中的拥有千条记录以上的表进行关联。两张表进行关联的字段都建有索引。但在实际查询中如果从B库进行两表的关联却会导致A库中大表的全表扫描,查询速度慢是次要的,关键是全表扫描会影响到A库的正常运行。
通过对SQL语句的不断调整、优化发现当两表进行简单的关联查询时,如果在select 后面采用"*"获取所有数据时,查询不会导致全表扫描,但在select 后面取具体字段时将会导致大表的全表扫描。
在简单查询的基础上进行group分组将直接导致大表的全表扫描,在此种情况下,所有的语句优化技巧都将失效,因为索引无效,此时必须采取特殊的方法建立起关联查询的索引,强制指定在关联过程中那一张表作为主要驱动表,那一张作为从表。在跨库关联查询的过程中,因为表不在同一个数据库中(同时在不同操作系统的服务器上)将导致关联过程中将一张表的数据提取到另一个数据库中进行关联。此时问题出现,如果在关联过程中将大表数据提取到小表所在库进行运算将导致大表的全表扫描,整个运算过程将非常慢且影响A库的正常运行。
最终解决全表扫描的办法是,如果在B库对不同数据库的两张大小表进行关联时,通过driving_site强制指定主驱动表,即以所指定的表为主要表,将其它表作为从表提取到驱动表所在的库进行关联运算。具体语句如下:
select /*+driving_site(main)*/ a.*,b.* from A.a main@BigTableDB,B.b minor where main.id=minor.id and .......
这样一来就可以避免大表所在库的全表扫描,查询速度将成级数级提高。
解释:
当指定 /*+driving_site(main)*/ 时, oracle将会从minor表获取全部数据到main表所在的数据库来进行关联运算.(索引起作用,速度快)
若指定 /*+driving_site(minor)*/ 时, oracle将会从main表获取全部数据到minor表所在的数据库来进行关联运算.(索引失败,全表扫描)
当然Oracle中有很多的关键字用于指定关联查询时的运算方法,等后面碰到具体应用实例实再作一一介绍。
引用:
DRIVING_SITE 作用和 ORDERED 类似。 DRIVING_SITE 通常在分布式查询中使用。如果没有这个提示, Oracle 会先从远程点检索,并将它们连接到本地站点中。通过使用 DRIVING_SITE ,我们可以先在本地进行检索,将检索后的数据发送到远程节点进行连接
优化案例:
--create or replace view v_fasp_bjjzzfyszxqkfld2 as
select a.bdgmanagedivision,a.gnkm,acctdate,sum(a.yszb) yszb,sum(a.zjzfjh) zjzfjh ,sum(a.sqzfjh) sqzfjh,
sum(a.zjzfzc) zjzfzc,sum(a.sqzfzc) sqzfzc,sum(a.zjzfjhjy) zjzfjhjy,sum(a.sqzfjhjy) sqzfjhjy
from
(select /*+ driving_site(t) */ t.mb_code as bdgmanagedivision,substr(t.bs_code,1,3) gnkm,substr(t.create_date,1,4)||substr(t.create_date,6,2)||substr(t.create_date,9,2) as acctdate,
sum(t.budget_money) yszb,0 as jhje, 0 as zjzfjh,0 as sqzfjh,0 as zcje,0 as zjzfzc,0 as sqzfzc,
--0 as zcjezt,0 as zjzfzczt,0 as sqzfzczt,
0 as jhjy,0 as zjzfjhjy,0 as sqzfjhjy
--0 as jhkyje,0 as zjzfjhkyje,0 as sqzfjhkyje
from vw_budget_useable_voucher@chunyuan_link t
where t.en_code not like '910%'
--and t.pk_code like '1%'
and t.bo_code='001001'
and t.is_end =1
and t.is_valid=1
and t.bl_code like '001001%' and t.budget_vou_id is not null group by t.mb_code,substr(t.bs_code,1,3),
substr(t.create_date,1,4)||substr(t.create_date,6,2)||substr(t.create_date,9,2) --支付系统录入指标
union all
select c.mb_code bdgmanagedivision,substr(c.bs_code,1,3) gnkm,plan_pay.acctdate,
0 as yszb,
nvl(plan_pay.zj_plan_money+plan_pay.sq_plan_money,0) jhje,
nvl(plan_pay.zj_plan_money,0) zjzfjh,nvl(plan_pay.sq_plan_money,0) sqzfjh,
nvl(plan_pay.zj_pay_money+plan_pay.sq_pay_Money,0) zcje,
nvl(plan_pay.zj_pay_money,0) zjzfzc,nvl(plan_pay.sq_pay_Money,0) sqzfzc,
nvl((plan_pay.zj_plan_money+plan_pay.sq_plan_money)-(plan_pay.zj_pay_money+plan_pay.sq_pay_Money),0) jhjy,
nvl(plan_pay.zj_plan_money,0)-nvl(plan_pay.zj_pay_money,0) zjzfjhjy,
nvl(plan_pay.sq_plan_money,0)-nvl(plan_pay.sq_pay_Money,0) sqzfjhjy
--20130507将gl_balance修改为(select sum_id,ccid from gl_balance_month_detail where set_month>0 group by sum_id,ccid) g
--解决计划额度ID号953119,6月份计划,新的额度,在GL_BALANCE表中还没有对应的记录。
from (select /*+ driving_site(c) */ sum_id,ccid,rcid from gl_balance_month_detail@chunyuan_link where set_month>0 group by sum_id,ccid,rcid) g,
vw_plan_voucher_nmg702@chunyuan_link c,
(select plan.toctrlid,plan.acctdate acctdate,
sum(zj_plan_money) zj_plan_money,
sum(sq_plan_money) sq_plan_money,
sum(zj_pay_money) zj_pay_money,
sum(sq_pay_Money) sq_pay_Money
from
--查询计划数据
(select /*+ driving_site(p) */ p.toctrlid,substr(p.create_date,1,4)||substr(p.create_date,6,2)||substr(p.create_date,9,2) as acctdate,
sum(case when p.PK_CODE like '11%' then p.plan_money else 0 end) zj_plan_money,
sum(case when p.PK_CODE like '12%' then p.plan_money else 0 end) sq_plan_money
from vw_plan_voucher@chunyuan_link p ,gl_journal@chunyuan_link g
where p.ID=g.vou_id and p.is_valid=1 and g.is_end=1 and g.set_month>0 and g.billtype_code not like '1%'
and p.budget_vou_id is not null
group by p.toctrlid,substr(p.create_date,1,4)||substr(p.create_date,6,2)||substr(p.create_date,9,2)
) plan,
--查询支出数据
(select /*+ driving_site(p) */ p.fromctrlid,substr(p.create_date,1,4)||substr(p.create_date,6,2)||substr(p.create_date,9,2) as acctdate,
sum(case when (p.PK_CODE like '11%' and p.clear_date is not null and g.is_end=1) then p.pay_money else 0 end) zj_pay_money,
sum(case when (p.PK_CODE like '12%' and p.clear_date is not null and g.is_end=1) then p.pay_money else 0 end) sq_pay_money
from vw_pay_voucher@chunyuan_link p ,gl_journal@chunyuan_link g
where p.ID=g.vou_id(+) and p.is_valid=1 and g.set_month>0 and g.billtype_code like '3%'
and p.budget_vou_id is not null
group by p.fromctrlid,substr(p.create_date,1,4)||substr(p.create_date,6,2)||substr(p.create_date,9,2)
) pay
where plan.toctrlid=pay.fromctrlid(+)
group by plan.toctrlid,plan.acctdate
) plan_pay
where g.sum_id=plan_pay.toctrlid and g.sum_id=c.toctrlid and g.rcid=c.rcid --and g.ccid=c.CCID and g.set_month>0
and (plan_pay.zj_pay_money<>'0' or plan_pay.sq_pay_Money<>'0' or plan_pay.zj_plan_money<>'0' or plan_pay.sq_plan_money<>'0')
and c.en_code not like '910%'
and c.bo_code='001001'
and c.bl_code like '001001%'
and exists(select /*+ driving_site(org) */ 1 from sys_user_org@chunyuan_link org where org.user_id = '7569' and org.org_id = c.MB_id) and 1=1
)a
group by a.bdgmanagedivision,a.gnkm,a.acctdate order by a.bdgmanagedivision,a.gnkm;