💡 인덱스로 검색해도 빠른데, 왜 굳이 파티셔닝?
인덱스로 검색하는데 왜 느림?
대량의 데이터를 조회하면 테이블 전체 스캔하는것보다 인덱스 사용하는것이 더 느리다.
인덱스를 스캔하는 이유는, 검색조건을 만족하는 소량의 데이터를 인덱스에서 빨리 찾아 테이블레코드를 찾아가기 위한 ROWID를 얻는것이다.
ROWID는 테이블 레코드를 찾아가기 위한 논리적 주소 정보를 담고있기 때문에 논리적인 주소에 가깝다.
ROWID를 포인터라고 이해하면 안된다.
인덱스 ROWID는 논리적 주소이다. 디스크상에서 테이블 레코드를 찾아가기 위한 정보를 담는다.
메인 메모리 DB (MMDB)는 데이터를 모두 메모리에 로드해놓고 메모리에서 I/O를 수행하는 DB이다.
그럼 버퍼캐시 히트율 99% DB와 MMDB를 비교하면 MMDB가 빠르다.
버퍼캐시 히트율 99%도 거의 메모리에서 I/O가 일어난다는데 왜?
즉, 일반 DBMS에서 인덱스 ROWID를 이용한 테이블 액세스가 생각보다 빠르지 않다.
클러스터링 팩터 (CF) : 군집성 계수
특정 컬럼을 기준으로 같은 값을 갖는 데이터가 서로 모여있는 정도를 의미.
CF가 좋은 컬럼에 생성한 인덱스는 검색 효율이 좋다. 그 의미는 테이블 액세스량에 비해 블록 I/O가 적게 발생한다는 뜻이다. (뭉쳐 있으니까 다 들리기 수월함.)
Index Range Scan에 의한 테이블 액세스가 Table Full Scan 보다 느려지는 지점을 말한다.
인덱스를 이용한 테이블 액세스가 Table Full Scan 보다 느린 이유는 아래와 같다.
인덱스 손익 분기점을 보고 좋은 인덱스를 만드려고 노력해야한다.
그리고 테이블스캔이 항상 나쁜건 아니고 인덱스 스캔이 항상 좋은건 아니다.
테이블 액세스 최소화를 위해 가장 일반적인 튜닝방법은 인덱스에 컬럼을 추가하는 것이다.
테이블 액세스 단계 필터 조건에 의해 버려지는 레코드가 많을 때, 인덱스에 컬럼을 추가하면 테이블 랜덤 액세스 횟수를 줄일 수 있다.
테이블 액세스 단계 필터 조건에 의해 버려지는 레코드가 많을땐, 인덱스에 컬럼 추가해서 성능 향상하지만, 만약 버려지는 레코드가 없다면 결국 테이블 랜덤 액세스가 많이 발생해 느릴수 밖에 없다.
이때, 쿼리에 사용된 컬럼을 모두 인덱스에 추가하여 테이블 액세스가 아예 발생하지 않게 할 수 있다. 이것을 Covered 쿼리라고 부르고, 그 쿼리에 사용한 인덱스를 'Covered 인덱스'라고 부른다.
하지만 실제로 추가해야 할 컬럼이 많아서 적용하기 곤란함.
Oracle엔 없지만 SQL Server2005에는 있는 기능이다.
인덱스 키 외에 미리 지정한 컬럼을 리프레벨에 함께 저장하는 기능이다.
Include 인덱스는 순전히 테이블 랜덤 액세스를 줄이는 용도로 개발됨.
인덱스를 이용한 테이블 액세스가 고비용 구조임. 그럼 랜덤 액세스가 아에 발생하지 않도록 테이블을 인덱스 구조로 생성한다면?
오라클은 이걸 IOT (Index Organized Table)라고 함. MS-SQL은 '클러스터형 인덱스'라고 함.
여러 테이블 레코드를 같은 블록에 저장한다. 이는 SQL Server의 클러서터형 인덱스와는 다르며 IOT에 가깝다.
클러스터 인덱스도 일반 B*Tree를 인덱스 구조를 사용하지만, 테이블 레코드를 일일이 가리키지 않고 해당 키값을 저장하는 첫 번째 데이터 블록을 가리킨다는 점이 다르다.
즉, 일반 테이블의 인덱스 레코드는 테이블 레코드와 1:1 대응 관계를 갖지만, 클러스터 인덱스는 테이블 레코드와 1:M관계를 가진다.
클러스터 인덱스의 키값은 항상 Unique하다.(중복값이 없다)
인덱스를 활용하지 않고 해시 알고리즘을 사용해 클러스터를 찾아간다.