데이터베이스는 디스크로 구성되어있는 데이터베이스이기 때문에 SQL 튜닝은 곧 I/O 튜닝이다. 그렇기에 기본적인 데이터의 저장 구조 및 디스크 또는 메모리를 읽는 메커니즘에 대한 정리를 먼저 해보자.
SQL 실행이 느려지는 이유
I/O가 처리되는 동안 다른 프로세스는 놀게된다. 그렇기 때문에 효율적인 프로세스 활용이 되지 못해 SQL이 느린 것이다. 왜냐하면 디스크에 접근하는 로직이 느린 경우 다른 프로세스는 계속 놀게되고 디스크 경합이 심해지기 때문이다.
데이터베이스 저장 구조
데이터베이스를 저장하려면 먼저 테이블 스페이스를 만들어야 한다. 테이블 스페이스는 테이블, 인덱스, 파티션, LOB등 여러 세그먼트를 담는 컨테이너로써 여러 개의 데이터파일로 구성된다.
각 세그먼트는 데이터 저장공간이 필요한 오브젝트이다. 그리고 그 세그먼트는 여러 익스텐트로 구성된다.익스텐트는 블록으로 구성되어 있는데, 테이블 또는 인덱스와 같은 데이터를 저장하다 공간이 부족하면 테이블 스페이스에게 요청하여 추가적으로 블록을 할당한다. 하나의 블록은 하나의 테이블이 독점한다. 즉 한 블록에 저장된 레코드는 모두 같은 테이블 레코드이다.
정리하면 이런 순서로 구성된다.
테이블 스페이스 > 세그먼트 > 익스텐트 > 블록
-> 각 블록은 한 테이블이 독점 (다중 테이블 클러스터일 경우 제외)
세그먼트 공간이 부족해졌을 때 새로운 익스텐트를 할당받는다고 했는데 그러면 그말은 익스텐트에 쓰다가 데이터 공간이 부족하면 새로운 익스텐트에 작성을 한다는 뜻으로 서로 다른 위치에 데이터가 저장된다는 뜻이다. 그렇기 때문에 이럴 경우 서로 다른 데이터 파일에 존재할 확률이 커진다. 왜냐면 테이블 스페이스는 데이터 파일로 구성되어 있는데 이는 DBMS가 파일 경합을 위해 분산시켜 놓기 때문이다.
결과적으로 그림에서 보면 알겠지만 테이블 스페이스는 크게보면 익스텐트들의 집합이다. 익스텐트들은 데이터 파일로써 분산되어 저장이된다. 그러기 때문에 익스텐트는 서로 붙어있게 만들어져있어서 세그먼트를 이루지만 데이터는 연속적인 인스텐트에 저장되는 것이 아니라는 것을 알수있다.
이런 세그먼트들에 할당되어 있는 익스텐트 목록을 조회하는 쿼리는 다음과 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | select segment_type, tablespace_name, extent_id, file_id, block_id, blocks from dba_extents where owner = USER order by extent_id; | cs |
실행 결과를 살펴보면 익스텐트별 데이터 파일 블록 아이디를 확인 할 수 있는데, 익스텐트가 연속되어서 저장되지는 않는다는 것을 알 수 있다. 서로 다른 블록에 저장된다.
정리하면
블록 : 데이터를 읽고 쓰는 단위
익스텐트 : 공간을 확장하는 단위, 연속된 블록 집합
세그먼트 : 데이터 저장공간이 필요한 오브젝트(테이블, 인덱스, 파티션, LOB 등)
테이블 스페이스 : 세그먼트를 담는 컨테이너
데이터파일 : 디스크 상의 물리적 OS 파일 (테이블 스페이스는 여러개의 데이터파일로 존재)
※ DBA (Data Block Address)
데이터가 몇번째 블록 어디에 위치해있는지 알려주는 주소를 의미
각 테이블에 레코드에 값을 읽을 때는 ROWID를 사용하는데 ROWID는 DBA + 블록내 순번을 의미
테이블을 스캔할 때는 각 세그먼트 헤더에 저장된 익스텐트 맵을 통해 필요한 블록의 위치로 이동한다.
'데이터베이스 > 친절한 SQL 튜닝' 카테고리의 다른 글
오라클의 논리적 I/O와 물리적 I/O의 차이 그리고 버퍼 캐시 히트율(BCHR) 구하기 (0) | 2018.06.28 |
---|---|
시퀀셜 액세스와 랜덤 액세스 (0) | 2018.06.28 |
바인드 변수를 이용한 오라클 SQL 튜닝 소개 (0) | 2018.06.19 |
오라클 옵티마이저의 소프트파싱(soft parsing)와 하드파싱(hard parsing) (0) | 2018.06.18 |
옵티마이저에게 사용할 인덱스(index) 힌트주기 (0) | 2018.06.18 |