DB LINK를 사용한 분산 쿼리의 튜닝
Nested Loop을 피하고, Hash Join 처리 하여, Network Round Trip 을 줄인다
- 네트웍을 통한 분산 SQL 튜닝에서,로컬 DB에서만 수행되는 SQL과 튜닝포인트가 다른 점
- 분산 DB QUERY의 NESTED LOOP 조인은 조인 건수만큼의 네트웍 RoundTrip이 발생
- 조인건수가 많을 경우 네트웍 Round Trip 에 대량 시간 발생
- 가급적 Sort-Merge나 Hash Join으로 수행되도록 PLAN을 조정하여, 조인으로 인한 Network Roundtrip을 줄이도록 유도
Driving_Site 힌트를 이용하여, 리모트 DB가 SQL 수행의 주체가 되도록 한다.
바인드변수나 문자열값의 직접 사용은 PLAN을 고정 시키게 된다.
Driving_Site 힌트로 리모트DB를 지정하여, PLAN을 조정 하는 경우,
- SQL에 바인드 변수 나 직접적인 문자열 값이 있는 경우 힌트가 원하는대로 적용되지 않음.
SQL에 SELECT-LIST에 문자열값 이나 바인드 변수 값이 있으면,
- PLAN상 Remote에서 수행이 되지 않고 항상 로컬에서 수행 됨.
- 이 경우 문자열이나 바인드 변수값을 제외한 SQL을 인라인 뷰에서 수행하게 하여 , Remote DB에서 해당 SQL이
- 수행되도록 하고, 인라인 뷰 밖에서 필요한 문자열 값을 주고, NO_MERGE 힌트를 사용하도록 합니다.
- * 변경 전 (DRIVING_SITE 힌트가 반영 되지 않음 )
INSERT INTO T3
SELECT /*+ DRIVING_SITE(T1) */
‘ADD_COLUMN’, T1.*, T2.*
FROM T1@LINK1 T1, T1@LINK1 T2
WHERE A.COL1 = B.COL2;
- * 변경 후 (DRIVING_SITE 힌트 반영)
INSERT INTO T3
SELECT /*+ NO_MERGE(A) DRIVING_SITE(A) */ 'ADD_COLUMN', A.*
FROM (
-- 리모트DB 에서 조인이 이루어 지도록
SELECT T1.*, T2.*
FROM T1@LINK1 T1, T1@LINK1 T2
WHERE A.COL1 = B.COL2) A;
- DRIVING_SITE 힌트를 줘도 리모트 DB에서 T1과 T2테이블을 로컬 DB로 읽어와서 로컬에서 조인.
- 리모트DB에서 조인해서 결과값만 받는 것이 일반적으로 유리함.
- 문자열값을 밖으로 뺀 인라인뷰와 NO_MERGE 힌트를 이용하여 원하는 PLAN으로 수정 가능.
- 뷰를 이용하여, PLAN 조정
- REMOTE 사이트의 테이블 여러개 RK 조인될 경우 해당 SQL을 해당 리모트사이트에 뷰를 만들어 놓는다면, 한번의 Remote Operation 만이 이루어질 것입니다.
- 즉, Driving_site 힌트가 제대로 수행이 되지 않는 경우 수행의 주체가 되기를 원하는 Remote DB상에 View를 생성하여 해당 View 를 SELECT 하여 PLAN을 조정
dblink로 가져올때는 병렬처리 불가
- 단일 dblink 통해 "병렬"을 수행할 수 없으며 dblink의 remote서버 병렬을 수행할 수 있지만 로컬로 가져올때는 네트워크 파이프가 하나만 있으므로 직렬로 연결됨
- 작업을 더 작은 조각으로 나누어야 함
- 가장 쉬운 방법은 각 파티션에 대한 작업(dbms_job, dbms_scheduler)을 설정하고 해당 작업에서 로드를 수행하는 것. 로컬 테이블이 같은 방식으로 분할된 경우 - 각 작업은 다음과 같이 동적 SQL을 사용하여 파티션을 로드합니다.
insert /*+ append */ into localtable partition( PNAME )
select * from remotetable@dblink partition(PNAME)
디비링크 네트워크 사용량 모니터링
수신된 바이트 수
-- total number of bytes received
select s.value
from v$sysstat s
, v$statname n
where n.name='bytes received via SQL*Net from dblink'
and n.statistic#=s.statistic#;
송신한 바이트 수
-- total number of bytes sent
select s.value
from v$sysstat s
, v$statname n
where n.name='bytes sent via SQL*Net to dblink'
and n.statistic#=s.statistic#;
송/수신 정보
--SQL*Net bytes sent for a session.
select *
from gv$sesstat
join v$statname
on gv$sesstat.statistic# = v$statname.statistic#
-- You probably also want to filter for a specific INST_ID and SID here.
where lower(display_name) like '%sql*net%';
--SQL*Net bytes sent for the entire system.
select *
from gv$sysstat
where lower(name) like '%sql*net%'
order by value desc;