본문 바로가기

IT관련

db file scattered read 와 direct path read 의 차이

Oracle AWR 리포트를 보거나 SQL Plan 을 보다보면, 이 2개의 Wait Event를 종종 보게됩니다.

 

          - db file scattered read

          - direct path read

 

둘다, 테이블을 Full Scan 하거나 인덱스를 Fast Full Scan 하는 경우에 나타나는 이벤트입니다.

참고로, 인덱스를 Range Scan 하는 경우에는 db file sequential read 이벤트가 발생합니다.

 

Index의 경우는 Index를 읽은 후, 다시 Table을 읽어야 하니 sequential 하게 읽는다고 생각하면 됩니다.

Full Scan의 경우는 여러 데이터블럭에서 통째로 많은 데이터를 한꺼번에 읽어야 하니, scattered(여기저기) 하게 read 한다고 생각하면 될 것 같습니다. 

 

그런데, 왜 어떤 경우는 db file scattered read 를 하고, 어떤 경우는 direct path read 를 할까요?

 

먼저, db file scattered read 는 Disk 에 있는 데이터블럭을 읽어서 Oracle DBMS의 공유메모리인 SGA(System Global Area)내의 버퍼캐시(Buffer Cache) 영역으로 로딩한 후, 사용자가 가져가는 형태입니다.

(엄밀히 말하면, 꼭 사용자가 바로 가져가는 것은 아니고.. 다른 테이블과 Join 을 하거나 Filtering 하거나 등등에 사용됩니다.)

 

direct path read 는 Disk 에 있는 데이터블럭을 읽는건 같은데, 이를 버퍼캐시 영역에 올리는 것이 아니라, 사용자의 개인 영역인 PGA(Private Global Area)에 로딩하는 방식입니다.

Disk 에서 읽는 것은 정말 힘든(?) 작업입니다. 시스템 입장에서 봤을때 CPU, Memory에 비해 너무나도 심하게 느린 놈이니까요.

이렇게 힘들게 읽은 데이터를 버퍼캐시(공유메모리)에 잘 보관해둔다면, 다른 프로세스들, 다른 SQL들도 이 데이터를 활용할 수 있으니 참 좋겠죠?

하지만, 버퍼캐시는 RAM 영역입니다. 비싸죠~ 많지 않습니다. 모든 데이터를 올려놓을 수가 없죠 ㅎㅎ

 

결국은 자주 쓰는 데이터들만 버퍼캐시에 남아 있어야 합니다.

큰 테이블 데이터의 경우 이게 db file scattered read 로 메모리에 올라가려면, 버퍼캐시에 있는 다른 데이터들을 밀어내서 공간을 확보해야 합니다. 이건 대형 참사를 일으킬 수 있죠~

자주 쓰는 작은 코드성 데이터가 지금까지는 메모리에 캐싱되어 있어서 0.01초만에 읽었었는데, 갑자기 옘병할 큰 테이블놈이 올라오는 바람에 이 코드테이블이 캐시에서 사라져서, 다시 Disk 에서 읽어오는 바람에 1초씩 걸린다고 생각해보십시요. ㅎㅎ 무려 100배가 느려지는 현상을 갑자기 체험하게 되는 것이죠^^

이게 한번이야 1초지만 이 짓을 한 100번 반복할 수도 있는 겁니다. 내부적으로 루핑돌면서...

이건 말그대로 대참사입니다.

 

그래서 이런 대참사를 막기위해 이때는 direct path read 를 하는 것이죠.

공유메모리인 버퍼캐시를 건드리지 않고, 개인 프로세스 메모리영역인 PGA에 올려서 다른 프로세스에 영향을 주지 않는게 목적입니다.

 

그럼, 어떤 것을 db file scattered read 를 하고, 어떤 것을 direct path read 를 할까요?

일반적으로 Parallel Query 를 하거나 대량의 데이터를 Sort 할 경우에 direct path read 를 하는 것으로 알려져 있습니다.

하지만, 꼭 Parallel Query 가 아니라도 일반적인 Serial Query 에서 "큰 테이블" 을 Full Scan 하는 경우에도 Oracle 이 알아서 direct path read 로 처리합니다.

 

마찬가지로 direct path write 라는 것도 있습니다.

버퍼캐시를 거치지 않고 직접 Disk(DB) 에 Writing 하는 것인데, insert 할때 /*+ append */ 힌트를 사용하거나 Parallel DML 처리를 하는 경우, 또는 SQL*Loader 로 로딩할때 direct 옵션을 사용하는 경우에 direct path write 를 사용합니다.